15c2acbbf16454d91d9079216f21427fdd33a609
hiram
  Tue Apr 16 13:45:20 2019 -0700
beginning to allow the array output time to function refs #18869

diff --git src/hg/hubApi/hubApi.c src/hg/hubApi/hubApi.c
index 5b3ef86..f6db268 100644
--- src/hg/hubApi/hubApi.c
+++ src/hg/hubApi/hubApi.c
@@ -18,30 +18,32 @@
 */
 
 /* Global Variables for all modules */
 
 int maxItemsOutput = 1000;	/* can be set in URL maxItemsOutput=N */
 static int maxItemLimit = 1000000;   /* maximum of 1,000,000 items returned */
 /* for debugging purpose, current bot delay value */
 int botDelay = 0;
 boolean debug = FALSE;	/* can be set in URL debug=1, to turn off: debug=0 */
 #define delayFraction	0.03
 
 /* default is to list all trackDb entries, composite containers too.
  * This option will limit to only the actual track entries with data
  */
 boolean trackLeavesOnly = FALSE;  /* set by CGI parameter 'trackLeavesOnly' */
+/* this selects output type 'arrays', where the default type is: objects */
+boolean jsonOutputArrays = FALSE; /* set by CGI parameter 'jsonOutputArrays' */
 
 /* Global only to this one source file */
 static struct cart *cart;             /* CGI and other variables */
 static struct hash *oldVars = NULL;
 static struct hash *trackCounter = NULL;
 static long totalTracks = 0;
 static boolean measureTiming = FALSE;	/* set by CGI parameters */
 static boolean allTrackSettings = FALSE;	/* checkbox setting */
 static char **shortLabels = NULL;	/* public hub short labels in array */
 static int publicHubCount = 0;
 static char *defaultHub = "Plants";
 static char *defaultDb = "ce11";
 static long enteredMainTime = 0;	/* will become = clock1000() on entry */
 		/* to allow calculation of when to bail out, taking too long */
 static long timeOutSeconds = 100;
@@ -212,102 +214,117 @@
 
 if (isNotEmpty(errorString))
     {
     safef(errorPrint, sizeof(errorPrint), " <font color='red'>ERROR: %s</font>", errorString);
     }
 
 boolean superChild = tdbIsSuperTrackChild(tdb);
 unsigned start = chromSize / 4;
 unsigned end = start + 10000;
 if (end > chromSize)
     end = chromSize;
 char *genome = NULL;
 if (hub)
     genome = hub->genomeList->name;
 
+struct dyString *extraDyFlags = newDyString(128);
+if (debug)
+    dyStringAppend(extraDyFlags, ";debug=1");
+if (jsonOutputArrays)
+    dyStringAppend(extraDyFlags, ";jsonOutputArrays=1");
+char *extraFlags = dyStringCannibalize(&extraDyFlags);
+
 if (db)
     {
     if (hub)
 	{
 	char urlReference[2048];
-	safef(urlReference,	sizeof(urlReference), " <a href='%s/getData/track?hubUrl=%s;genome=%s;track=%s;chrom=%s;start=%u;end=%u' target=_blank>(sample data)%s</a>\n", urlPrefix, hub->url, genome, tdb->track, chrom, start, end, errorPrint);
+	safef(urlReference,	sizeof(urlReference), " <a href='%s/getData/track?hubUrl=%s;genome=%s;track=%s;chrom=%s;start=%u;end=%u%s' target=_blank>(sample data)%s</a>\n", urlPrefix, hub->url, genome, tdb->track, chrom, start, end, extraFlags, errorPrint);
 
 	if (tdb->parent)
 	    hPrintf("<li><b>%s</b>: %s subtrack of parent: %s%s</li>\n", tdb->track, tdb->type, tdb->parent->track, urlReference);
 	else
 	    hPrintf("<li><b>%s</b>: %s%s</li>\n", tdb->track, tdb->type, urlReference);
 	}
     else
 	{
 	char urlReference[2048];
-	safef(urlReference, sizeof(urlReference), " <a href='%s/getData/track?db=%s;chrom=%s;track=%s;start=%u;end=%u' target=_blank>(sample data)%s</a>\n", urlPrefix, db, chrom, tdb->track, start, end, errorPrint);
+	safef(urlReference, sizeof(urlReference), " <a href='%s/getData/track?db=%s;chrom=%s;track=%s;start=%u;end=%u%s' target=_blank>(sample data)%s</a>\n", urlPrefix, db, chrom, tdb->track, start, end, extraFlags, errorPrint);
 
 	if (superChild)
 	    hPrintf("<li><b>%s</b>: %s superTrack child of parent: %s%s</li>\n", tdb->track, tdb->type, tdb->parent->track, urlReference);
 	else if (tdb->parent)
 	    hPrintf("<li><b>%s</b>: %s subtrack of parent: %s%s</li>\n", tdb->track, tdb->type, tdb->parent->track, urlReference);
 	else
 	    hPrintf("<li><b>%s</b>: %s%s</li>\n", tdb->track, tdb->type, urlReference );
 	}
     }
 else if (hub)
     {
     char urlReference[2048];
-    safef(urlReference, sizeof(urlReference), " <a href='%s/getData/track?hubUrl=%s;genome=%s;track=%s;chrom=%s;start=%u;end=%u' target=_blank>(sample data)%s</a>\n", urlPrefix, hub->url, genome, tdb->track, chrom, start, end, errorPrint);
+    safef(urlReference, sizeof(urlReference), " <a href='%s/getData/track?hubUrl=%s;genome=%s;track=%s;chrom=%s;start=%u;end=%u%s' target=_blank>(sample data)%s</a>\n", urlPrefix, hub->url, genome, tdb->track, chrom, start, end, extraFlags, errorPrint);
 
     if (tdb->parent)
 	hPrintf("<li><b>%s</b>: %s subtrack of parent: %s%s</li>\n", tdb->track, tdb->type, tdb->parent->track, urlReference);
     else
 	hPrintf("<li><b>%s</b>: %s%s</li>\n", tdb->track, tdb->type, urlReference);
     }
 else
     hPrintf("<li>%s : %s not db hub track ?</li>\n", tdb->track, tdb->type);
 }
 
 static void hubSampleUrl(struct trackHub *hub, struct trackDb *tdb,
     long chromCount, long itemCount, char *chromName, unsigned chromSize,
       char *genome, char *errorString)
 {
 unsigned start = chromSize / 4;
 unsigned end = start + 10000;
 if (end > chromSize)
     end = chromSize;
 
+
+struct dyString *extraDyFlags = newDyString(128);
+if (debug)
+    dyStringAppend(extraDyFlags, ";debug=1");
+if (jsonOutputArrays)
+    dyStringAppend(extraDyFlags, ";jsonOutputArrays=1");
+char *extraFlags = dyStringCannibalize(&extraDyFlags);
+
 char errorPrint[2048];
 errorPrint[0] = 0;
 
 if (isNotEmpty(errorString))
     {
     safef(errorPrint, sizeof(errorPrint), " : <font color='red'>ERROR: %s</font>", errorString);
     }
 
 char countsMessage[512];
 countsMessage[0] = 0;
 if (chromCount > 0 || itemCount > 0)
     {
     if (allowedBigBedType(tdb->type))
         safef(countsMessage, sizeof(countsMessage), " : %ld chroms : %ld item count ", chromCount, itemCount);
     else if (startsWithWord("bigWig", tdb->type))
         safef(countsMessage, sizeof(countsMessage), " : %ld chroms : %ld bases covered ", chromCount, itemCount);
     else
         safef(countsMessage, sizeof(countsMessage), " : %ld chroms : %ld count ", chromCount, itemCount);
     }
 
 if (isSupportedType(tdb->type))
     {
 	char urlReference[2048];
-	safef(urlReference, sizeof(urlReference), "<a href='%s/getData/track?hubUrl=%s;genome=%s;track=%s;chrom=%s;start=%u;end=%u' target=_blank>(sample data)%s</a>\n", urlPrefix, hub->url, genome, tdb->track, chromName, start, end, errorPrint);
+	safef(urlReference, sizeof(urlReference), "<a href='%s/getData/track?hubUrl=%s;genome=%s;track=%s;chrom=%s;start=%u;end=%u%s' target=_blank>(sample data)%s</a>\n", urlPrefix, hub->url, genome, tdb->track, chromName, start, end, extraFlags, errorPrint);
 
 	if (allowedBigBedType(tdb->type))
             hPrintf("    <li><b>%s</b>: %s%s%s</li>\n", tdb->track, tdb->type, countsMessage, urlReference);
         else if (startsWithWord("bigWig", tdb->type))
             hPrintf("    <li><b>%s</b>: %s%s%s</li>\n", tdb->track, tdb->type, countsMessage, urlReference);
         else
             hPrintf("    <li><b>%s</b>: %s%s%s</li>\n", tdb->track, tdb->type, countsMessage, urlReference);
     }
 else
     {
         if (allowedBigBedType(tdb->type))
             hPrintf("    <li><b>%s</b>: %s%s</li>\n", tdb->track, tdb->type, countsMessage);
         else if (startsWithWord("bigWig", tdb->type))
             hPrintf("    <li><b>%s</b>: %s%s</li>\n", tdb->track, tdb->type, countsMessage);
         else
@@ -1094,31 +1111,31 @@
 char *hogHost = getenv("REMOTE_ADDR");
 char *pathInfo = getenv("PATH_INFO");
 /* nothing on incoming path, then display the WEB page instead */
 if (sameOk("/",pathInfo))
     pathInfo = NULL;
 if (isNotEmpty(pathInfo))
     {
     sendJsonHogMessage(hogHost);
     }
 else
     {
     sendHogMessage(hogHost);
     }
 }	/*	static void hogExit()	*/
 
-/* name of button group */
+/* name of radio button group */
 #define RADIO_GROUP	"selectRadio"
 /* button functions */
 #define RADIO_PUBHUB	"pubHub"
 #define RADIO_OTHERHUB	"otherHub"
 #define RADIO_UCSCDB	"ucscDb"
 
 static void selectionForm()
 /* setup the selection pull-downs for source */
 {
 char *hubDropDown = cartUsualString(cart, "publicHubs", defaultHub);
 char *urlDropDown = urlFromShortLabel(hubDropDown);
 char *otherHubUrl = cartUsualString(cart, "urlHub", "");
 char *ucscDb = cartUsualString(cart, "ucscGenome", defaultDb);
 
 if (isEmpty(otherHubUrl))
@@ -1183,37 +1200,42 @@
 hWrites("</th><td>");
 maxDbNameWidth *= 9;  // 9 should be font width here
 char widthPx[SMALLBUF];
 safef(widthPx, sizeof(widthPx), "width: %dpx", maxDbNameWidth);
 cgiMakeDropListClassWithIdStyleAndJavascript("ucscGenome", "ucscGenome",
     ucscDbList, ucscDataBaseCount, ucscDb, NULL, widthPx, events);
 jsOnEventById("change", "ucscGenome", "document.getElementById('"RADIO_GROUP"_"RADIO_UCSCDB"').checked=true;");
 hWrites("</td></tr>\n");
 
 allTrackSettings = cartUsualBoolean(cart, "allTrackSettings", FALSE);
 hWrites("<tr><td>&nbsp;</td><th>display control:</th><td>");
 hCheckBox("allTrackSettings", allTrackSettings);
 hWrites("&nbsp;display all track settings for each track");
 hWrites("</td></tr>\n");
 
-
 trackLeavesOnly = cartUsualBoolean(cart, "trackLeavesOnly", trackLeavesOnly);
 hWrites("<tr><td>&nbsp;</td><th>JSON list output:</th><td>");
 hCheckBox("trackLeavesOnly", trackLeavesOnly);
 hWrites("&nbsp;show only data tracks, do not show composite container information");
 hWrites("</td></tr>\n");
 
+jsonOutputArrays = cartUsualBoolean(cart, "jsonOutputArrays", jsonOutputArrays);
+hWrites("<tr><td>&nbsp;</td><th>JSON output type:</th><td>");
+hCheckBox("jsonOutputArrays", jsonOutputArrays);
+hWrites("&nbsp;more array data than objects (default: mostly object output)");
+hWrites("</td></tr>\n");
+
 /* go button at the bottom of the table */
 hWrites("<tr><td>&nbsp;</td><td align=center>");
 hButton("sourceSelected", "go");
 hWrites("</td><td>press 'go' after selections made</td></tr>\n");
 
 hPrintf("</form>\n");
 
 hPrintf("<tr><th colspan=3>(example JSON list output: <a href='/list/publicHubs' target=_blank>Public hubs</a>, and <a href='/list/ucscGenomes' target=_blank>UCSC database genomes</a>)</th></tr>\n");
 
 hPrintf("</table>\n");
 hPrintf("</td></tr></table>\n");
 
 /* how does debug carry forward ? */
 // if (debug)
 //    cgiMakeHiddenVar("debug", "1");
@@ -1224,30 +1246,31 @@
 {
 cart = theCart;
 measureTiming = hPrintStatus() && isNotEmpty(cartOptionalString(cart, "measureTiming"));
 measureTiming = TRUE;
 char *database = NULL;
 char *genome = NULL;
 
 cgiVarSet("ignoreCookie", "1");
 
 getDbAndGenome(cart, &database, &genome, oldVars);
 initGenbankTableNames(database);
 initSupportedTypes();
 initUrlPrefix();
 
 trackLeavesOnly = cartUsualBoolean(cart, "trackLeavesOnly", trackLeavesOnly);
+jsonOutputArrays = cartUsualBoolean(cart, "jsonOutputArrays", jsonOutputArrays);
 
 /* global variable for all workers to honor this limit */
 maxItemsOutput = cartUsualInt(cart, "maxItemsOutput", maxItemsOutput);
 if (maxItemsOutput < 0)	/* can use -1 to indicate as much as allowed */
     maxItemsOutput = maxItemLimit;
 /* maxItemsOutput of 0 might be useful, to be seen, let it go through */
 // if (maxItemsOutput < 1)	/* safety check */
 //     maxItemsOutput = 1;
 
 if (maxItemsOutput > maxItemLimit)	/* safety check */
     maxItemsOutput = maxItemLimit;
 
 debug = cartUsualBoolean(cart, "debug", debug);
 
 int timeout = cartUsualInt(cart, "udcTimeout", 300);