88485cfa7f13affa28ec5765fe9b2db90cce42b6
markd
  Tue Dec 8 21:02:15 2020 -0800
hgPcr working

diff --git src/hg/hgPcr/hgPcr.c src/hg/hgPcr/hgPcr.c
index cf9eaf9..f08b185 100644
--- src/hg/hgPcr/hgPcr.c
+++ src/hg/hgPcr/hgPcr.c
@@ -1,30 +1,32 @@
 /* hgPcr - In-silico PCR CGI for UCSC. */
 
 /* Copyright (C) 2014 The Regents of the University of California 
  * See README in this or parent directory for licensing information. */
 #include "common.h"
 #include "hash.h"
 #include "errAbort.h"
 #include "errCatch.h"
 #include "hCommon.h"
+#include "hgConfig.h"
 #include "dystring.h"
 #include "jksql.h"
 #include "linefile.h"
 #include "dnautil.h"
 #include "fa.h"
 #include "psl.h"
+#include "genoFind.h"
 #include "gfPcrLib.h"
 #include "cheapcgi.h"
 #include "htmshell.h"
 #include "hdb.h"
 #include "hui.h"
 #include "cart.h"
 #include "dbDb.h"
 #include "blatServers.h"
 #include "targetDb.h"
 #include "pcrResult.h"
 #include "trashDir.h"
 #include "web.h"
 #include "botDelay.h"
 #include "oligoTm.h"
 #include "trackHub.h"
@@ -44,94 +46,109 @@
   "options:\n"
   "   -xxx=XXX\n"
   );
 }
 
 struct pcrServer
 /* Information on a server running on genomic assembly sequence. */
    {
    struct pcrServer *next;  /* Next in list. */
    char *db;		/* Database name. */
    char *genome;	/* Genome name. */
    char *description;	/* Assembly description */
    char *host;		/* Name of machine hosting server. */
    char *port;		/* Port that hosts server. */
    char *seqDir;	/* Directory of sequence files. */
+   boolean isDynamic;   /* is a dynamic server */
+   char* genomeDataDir; /* genome name for dynamic gfServer  */
    };
 
 struct targetPcrServer
 /* Information on a server running on non-genomic sequence, e.g. mRNA,
  * that has been aligned to a particular genomic assembly. */
    {
    struct targetPcrServer *next;  /* Next in list. */
    char *host;		/* Name of machine hosting server. */
    char *port;		/* Port that hosts server. */
    struct targetDb *targetDb;     /* All of the info about the target. */
    };
 
 struct pcrServer *getTrackHubServers()
 /* Get the list of track hubs that have PCR services. */
 {
 struct pcrServer *serverList = NULL, *server;
 
 struct dbDb *dbDbList = trackHubGetPcrServers();
 
 for(; dbDbList; dbDbList = dbDbList->next)
     {
     AllocVar(server);
     server->db = dbDbList->name;
     server->genome = dbDbList->organism;
     server->description = dbDbList->description;
-    trackHubGetPcrParams(server->db, &server->host, &server->port);
+    trackHubGetPcrParams(server->db, &server->host, &server->port, &server->genomeDataDir);
     struct trackHubGenome *genome = trackHubGetGenome(server->db);
     server->seqDir = cloneString(genome->twoBitPath);
     char *ptr = strrchr(server->seqDir, '/');
     // we only want the directory name
     if (ptr != NULL)
          *ptr = 0;
     slAddHead(&serverList, server);
     }
 
 return serverList;
 }
 
 struct pcrServer *getServerList()
 /* Get list of available servers. */
 {
 struct pcrServer *serverList = NULL, *server;
 struct sqlConnection *conn = hConnectCentral();
 struct sqlResult *sr;
 char **row;
 
 serverList = getTrackHubServers();
 
-/* Do a little join to get data to fit into the pcrServer. */
-sr = sqlGetResult(conn, 
-   NOSQLINJ "select dbDb.name,dbDb.genome,dbDb.description,blatServers.host,"
-   "blatServers.port,dbDb.nibPath "
-   "from dbDb,blatServers where "
+/* Do a little join to get data to fit into the pcrServer.  Check for newer
+ * dynamic flag and allow with or without it.  For debugging, one set the
+ * variable blatServersTbl to some db.table to pick up settings from somewhere
+ * other than dbDb.blatServers. */
+char *blatServersTbl = cfgOptionDefault("blatServersTbl", "blatServers");
+boolean haveDynamic = sqlColumnExists(conn, blatServersTbl, "dynamic");
+char query[512];
+sqlSafef(query, sizeof(query),
+         "select dbDb.name,dbDb.genome,dbDb.description,blatServers.host,"
+         "blatServers.port,dbDb.nibPath, %s "
+         "from dbDb, %s blatServers where "
          "dbDb.name = blatServers.db "
-   "and blatServers.canPcr = 1 order by dbDb.orderKey" );
+         "and blatServers.canPcr = 1 order by dbDb.orderKey",
+         (haveDynamic ? "blatServers.dynamic" : "0"), blatServersTbl);
+sr = sqlGetResult(conn, query);
 while ((row = sqlNextRow(sr)) != NULL)
     {
     AllocVar(server);
     server->db = cloneString(row[0]);
     server->genome = cloneString(row[1]);
     server->description = cloneString(row[2]);
     server->host = cloneString(row[3]);
     server->port = cloneString(row[4]);
     server->seqDir = hReplaceGbdbSeqDir(row[5], server->db);
+    if (atoi(row[6]))
+        {
+        server->isDynamic = TRUE;
+        server->genomeDataDir = cloneString(server->db);  // directories by database name for database genomes
+        }
     slAddHead(&serverList, server);
     }
 sqlFreeResult(&sr);
 hDisconnectCentral(&conn);
 if (serverList == NULL)
     errAbort("Sorry, no PCR servers are available");
 slReverse(&serverList);
 return serverList;
 }
 
 struct pcrServer *findServer(char *db, struct pcrServer *serverList)
 /* Return server for given database.  Db can either be
  * database name or description. */
 {
 struct pcrServer *server;
@@ -364,30 +381,31 @@
 	       hGenome(db), hFreezeDate(db), organism, hFreezeDate(orgServer->db));
     *pDb = db = orgServer->db;
     }
 }
 
 void doGetPrimers(char *db, char *organism, struct pcrServer *serverList,
 	char *fPrimer, char *rPrimer, int maxSize, int minPerfect, int minGood,
 	boolean flipReverse)
 /* Put up form to get primers. */
 {
 redoDbAndOrgIfNoServer(serverList, &db, &organism);
 struct sqlConnection *conn = hConnectCentral();
 boolean gotTargetDb = sqlTableExists(conn, "targetDb");
 hDisconnectCentral(&conn);
 
+
 printf("<FORM ACTION=\"../cgi-bin/hgPcr\" METHOD=\"GET\" NAME=\"mainForm\">\n");
 cartSaveSession(cart);
 
 printf("<TABLE BORDER=0 WIDTH=\"96%%\" COLS=7><TR>\n");
 
 printf("%s", "<TD><CENTER>\n");
 printf("Genome:<BR>");
 showGenomes(organism, serverList);
 printf("%s", "</TD>\n");
 
 printf("%s", "<TD><CENTER>\n");
 printf("Assembly:<BR>");
 showAssemblies(organism, db, serverList, gotTargetDb);
 printf("%s", "</TD>\n");
 
@@ -495,62 +513,65 @@
 trashDirFile(&primerTn, "hgPcr", "hgPcr", ".txt");
 gfPcrOutputWriteAll(gpoList, "psl", NULL, bedTn.forCgi);
 writePrimers(gpoList, primerTn.forCgi);
 if (isNotEmpty(target))
     safef(buf, sizeof(buf), "%s %s %s", bedTn.forCgi, primerTn.forCgi, target);
 else
     safef(buf, sizeof(buf), "%s %s", bedTn.forCgi, primerTn.forCgi);
 cartSetString(cart, cartVar, buf);
 }
 
 
 void doQuery(struct pcrServer *server, struct gfPcrInput *gpi,
 	     int maxSize, int minPerfect, int minGood)
 /* Send a query to a genomic assembly PCR server and print the results. */
 {
+struct gfConnection *conn = gfConnect(server->host, server->port,
+                                      trackHubDatabaseToGenome(server->db), server->genomeDataDir);
 struct gfPcrOutput *gpoList =
-    gfPcrViaNet(server->host, server->port, server->seqDir, gpi,
+    gfPcrViaNet(conn, server->seqDir, gpi,
 		maxSize, minPerfect, minGood);
 if (gpoList != NULL)
     {
     char urlFormat[2048];
     safef(urlFormat, sizeof(urlFormat), "%s?%s&db=%s&position=%%s:%%d-%%d"
 	  "&hgPcrResult=pack", 
 	  hgTracksName(), cartSidUrlString(cart), server->db);
     printf("<TT><PRE>");
     gfPcrOutputWriteAll(gpoList, "fa", urlFormat, "stdout");
     printf("</PRE></TT>");
     writePcrResultTrack(gpoList, server->db, NULL);
     }
 else
     {
     printf("No matches to %s %s in %s %s", gpi->fPrimer, gpi->rPrimer, 
 	   server->genome, server->description);
     }
+gfDisconnect(&conn);
 }
 
 void doTargetQuery(struct targetPcrServer *server, struct gfPcrInput *gpi,
 		   int maxSize, int minPerfect, int minGood)
 /* Send a query to a non-genomic target PCR server and print the results. */
 {
+struct gfConnection *conn = gfConnect(server->host, server->port, NULL, NULL);
 struct gfPcrOutput *gpoList;
 char seqDir[PATH_LEN];
 splitPath(server->targetDb->seqFile, seqDir, NULL, NULL);
 if (endsWith("/", seqDir))
     seqDir[strlen(seqDir) - 1] = '\0';
-gpoList = gfPcrViaNet(server->host, server->port, seqDir, gpi,
-		      maxSize, minPerfect, minGood);
+gpoList = gfPcrViaNet(conn, seqDir, gpi, maxSize, minPerfect, minGood);
 if (gpoList != NULL)
     {
     struct gfPcrOutput *gpo;
     char urlFormat[2048];
     printf("The sequences and coordinates shown below are from %s, "
 	   "not from the genome assembly.  The links lead to the "
 	   "Genome Browser at the position of the entire target "
 	   "sequence.<BR>\n",
 	   server->targetDb->description);
     printf("<TT><PRE>");
     for (gpo = gpoList;  gpo != NULL;  gpo = gpo->next)
 	{
 	/* Not used as a format here; we modify the name used for position: */
 	safef(urlFormat, sizeof(urlFormat), "%s?%s&db=%s&position=%s"
 	      "&hgPcrResult=pack", 
@@ -558,30 +579,31 @@
 	      pcrResultItemAccession(gpo->seqName));
 	if (gpo->strand == '-')
 	    printf("<EM>Warning: this amplification is on the reverse-"
 		   "complement of %s</EM>.\n", gpo->seqName);
 	gfPcrOutputWriteOne(gpo, "fa", urlFormat, stdout);
 	printf("\n");
 	}
     printf("</PRE></TT>");
     writePcrResultTrack(gpoList, server->targetDb->db, server->targetDb->name);
     }
 else
     {
     printf("No matches to %s %s in %s", gpi->fPrimer, gpi->rPrimer, 
 	   server->targetDb->description);
     }
+gfDisconnect(&conn);
 }
 
 boolean doPcr(struct pcrServer *server, struct targetPcrServer *targetServer,
 	char *fPrimer, char *rPrimer, 
 	int maxSize, int minPerfect, int minGood, boolean flipReverse)
 /* Do the PCR, and show results. */
 {
 struct errCatch *errCatch = errCatchNew();
 boolean ok = FALSE;
 
 hgBotDelay();
 if (flipReverse)
     reverseComplement(rPrimer, strlen(rPrimer));
 if (errCatchStart(errCatch))
     {