51d1bcdbeac4b2ee7ce4d749c2a975e8bd8a72b1
galt
  Wed May 27 18:34:11 2020 -0700
added -timeout=1 and -host=blat1a options

diff --git src/hg/utils/blatServersCheck/blatServersCheck.c src/hg/utils/blatServersCheck/blatServersCheck.c
index f5617a3..6c2dc69 100644
--- src/hg/utils/blatServersCheck/blatServersCheck.c
+++ src/hg/utils/blatServersCheck/blatServersCheck.c
@@ -12,82 +12,102 @@
 #include "hgConfig.h"
 #include "genoFind.h"
 #include "net.h"
 #include "hash.h"
 #include "obscure.h"
 
 char *database = NULL;
 char *host     = NULL;
 char *user     = NULL;
 char *password = NULL;
 
 struct sqlConnection *conn = NULL;
 
 char *blatServersTableName = "blatServers";
 
+int timeout = 10;  // default timeout in seconds
+
+char *hostFilter = NULL;  // default to searching all hosts
+
 void usage()
 /* Explain usage and exit. */
 {
 errAbort(
   "blatServersCheck - Check the blatServers table matches running gfServers\n"
   "usage:\n"
   "   blatServersCheck profile\n"
   "profile should be from hg.conf like central or rrcentral\n"
   "options:\n"
+  " -timeout=10 timeout in seconds.\n"
+  " -host=blatx only check records with matching host.\n"
   " -verbose=2  can show details for each server.\n"
   "\n"
   );
 }
 
 
 static struct optionSpec options[] = {
+   {"timeout", OPTION_INT},
+   {"host",  OPTION_STRING},
    {"-help", OPTION_BOOLEAN},
    {NULL, 0},
 };
 
 char *getCfgOption(char *config, char *setting)
 /* get setting for specified config */
 {
 char temp[256];
 safef(temp, sizeof(temp), "%s.%s", config, setting);
 char *value = cfgOption(temp);
 if (!value)
     errAbort("setting %s not found!",temp);
 return value;
 }
 
+void setSocketTimeout(int sockfd, int delayInSeconds)
+// put socket read timeout so it will not take forever to timeout during a read
+{
+struct timeval tv;
+tv.tv_sec = delayInSeconds;
+tv.tv_usec = 0;
+setsockopt(sockfd, SOL_SOCKET, SO_RCVTIMEO, (const char*)&tv, sizeof tv);
+setsockopt(sockfd, SOL_SOCKET, SO_SNDTIMEO, (const char*)&tv, sizeof tv);
+}
+
 int statusServer(char *hostName, char *portName, boolean isTrans, struct hash *versionHash)
 /* Send status message to server arnd report result.
  * Returns -1 for connection error.
  * Returns -2 for error reading string.
  * Returns -3 for type mismatch.
  * Returns -4 for host mismatch.
  * Returns -5 for port mismatch.
  */
 {
 char buf[256];
 int sd = 0;
 int ret = 0;
 
 /* Put together command. */
-sd = gfMayConnect(hostName, portName);
+sd = netConnectWithTimeout(hostName, atoi(portName), timeout * 1000); // 10 seconds connect timeout
 if (sd == -1)
     {
     warn("Error connecting to %s:%s",  hostName, portName);
     return -1;
     }
 
+setSocketTimeout(sd, timeout);
+
 sprintf(buf, "%sstatus", gfSignature());
 mustWriteFd(sd, buf, strlen(buf));
 
 for (;;)
     {
     if (netGetString(sd, buf) == NULL)
         {
         warn("Error reading status information from %s:%s",  hostName, portName);
         ret = -2;  // error reading response
         break;
         }
     if (sameString(buf, "end"))
 	{
         break;
 	}
@@ -144,31 +164,34 @@
  * Returns -1 for 2bit name mismatch
  * Returns -2 for name mot found in targetDb, probably obsolete
  * Returns -3 for targetDb.seqFile does not match fileName on gfServer
  */
 {
 char buf[256];
 int sd = 0;
 int fileCount;
 int i;
 int ret = 0;
 char twoBitName[256];
 
 safef(twoBitName, sizeof twoBitName, "%s.2bit", db);
 
 /* Put together command. */
-sd = netMustConnectTo(hostName, portName);
+sd = netConnectWithTimeout(hostName, atoi(portName), timeout * 1000); // 10 seconds connect timeout
+
+setSocketTimeout(sd, timeout);
+
 sprintf(buf, "%sfiles", gfSignature());
 mustWriteFd(sd, buf, strlen(buf));
 
 /* Get count of files, and then each file name. */
 if (netGetString(sd, buf) != NULL)
     {
     fileCount = atoi(buf);
     for (i=0; i<fileCount; ++i) // could have multiples if .nib used?
 	{
 	char *fileName = netRecieveString(sd, buf);
 	//printf("%s\n", fileName);
 	verbose(2, "%s\n", fileName);
 	// if .nib, cannot confirm the name.
 	if (endsWith(fileName,".nib"))
             {
@@ -256,48 +279,53 @@
 
 getTargetDb(conn, targetDbHash);
 
 struct sqlResult *sr;
 char **row;
 char query[256];
 int totalRows = 0;
 
 verbose(1, "-------------------\n");
 verbose(1, "Reading table %s\n", blatServersTableName);
 
 
 totalRows = sqlTableSize(conn, blatServersTableName);
 verbose(1,"totalRows=%d\n", totalRows);
 
+verbose(1,"\n");
+
 if (totalRows==0)
     {
     errAbort("table %s is empty!", blatServersTableName);
     }
 
 int errCount = 0;
 
 sqlSafef(query,sizeof(query), "select db, host, port, isTrans from %s", blatServersTableName);
 sr = sqlGetResult(conn, query);
 while ((row = sqlNextRow(sr)) != NULL)
     {
     char *db      = row[0];
     char *host    = row[1];
     char *portStr = row[2];
     unsigned int port  = sqlUnsigned(portStr);
     unsigned int trans = sqlUnsigned(row[3]);
     boolean isTrans = (trans == 1);
 
+    if (hostFilter && !sameString(hostFilter, host))
+	continue;   // skip
+
     int res = statusServer(host, portStr, isTrans, versionHash);
     int res2 = 0;
     if (res != -1)  // if not a connection error, proceed.
 	{
 	res2 = getFileList(host, portStr, db, targetDbHash);
 	}
     safef(hashKey, sizeof hashKey, "%s:%s", host, portStr);
     struct hashEl *hel = hashLookup(hash, hashKey);
     if (hel == NULL)
 	{
 	hashAdd(hash, hashKey, NULL);
 	}
     else
 	{
 	warn("duplicate host:port %s found", hashKey);
@@ -332,21 +360,25 @@
 verbose(1, "\n");
 
 if (errCount > 0)
     errAbort("error count=%d", errCount);
 }
 
 
 int main(int argc, char *argv[])
 /* Process command line. */
 {
 optionInit(&argc, argv, options);
 
 if ((argc != 2) || optionExists("-help"))
     usage();
 
+timeout = optionInt("timeout", timeout);
+
+hostFilter = optionVal("host", hostFilter);
+
 blatServersCheck(argv[1]);
 
 printf("No errors found!\n");
 
 return 0;  
 }