1fab075a58052c812dc69b9609cc987b400985cc hiram Mon Apr 22 22:05:40 2019 -0700 getting to api functions immediately no cart involved refs #18869 diff --git src/hg/hubApi/hubApi.c src/hg/hubApi/hubApi.c index 43826cd..ff5c858 100644 --- src/hg/hubApi/hubApi.c +++ src/hg/hubApi/hubApi.c @@ -195,46 +195,42 @@ { hashIncInt(countTracks, "superTrack child"); hashIncInt(countTracks, stripType); hashIncInt(countTracks, "track count"); } else if (isEmpty(tdb->type)) hashIncInt(countTracks, "no type specified"); else { hashIncInt(countTracks, stripType); hashIncInt(countTracks, "track count"); } freeMem(stripType); } -static void sampleUrl(struct trackHub *hub, char *db, struct trackDb *tdb, char *chrom, unsigned chromSize, char *errorString) +static void sampleUrl(struct trackHub *hub, char *db, struct trackDb *tdb, char *errorString) /* print out a sample getData URL */ { char errorPrint[2048]; errorPrint[0] = 0; 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) { @@ -262,39 +258,32 @@ else if (hub) { char urlReference[2048]; safef(urlReference, sizeof(urlReference), " <a href='%s/getData/track?hubUrl=%s;genome=%s;track=%s;maxItemsOutput=5%s' target=_blank>(sample data)%s</a>\n", urlPrefix, hub->url, genome, tdb->track, 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) + long chromCount, long itemCount, 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); } @@ -320,32 +309,31 @@ 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 hPrintf(" <li><b>%s</b>: %s%s</li>\n", tdb->track, tdb->type, countsMessage); } } /* static void hubSampleUrl(struct trackHub *hub, struct trackDb *tdb, - * long chromCount, long itemCount, char *chromName, unsigned chromSize, - * char *genome) + * long chromCount, long itemCount, char *genome) */ static void bbiLargestChrom(struct bbiChromInfo *chromList, char **chromName, unsigned *chromSize) /* find largest chromosome name and size in the chromList */ { if (chromName && chromSize) { *chromSize = 0; char *returnName = NULL; struct bbiChromInfo *el; for (el = chromList; el; el = el->next) { if (el->size > *chromSize) { @@ -487,60 +475,60 @@ bigDataIndex = trackHubRelativeUrl(hub->genomeList->trackDbFile, relIdxUrl); char *bigDataUrl = trackDbSetting(tdbEl, "bigDataUrl"); char *longName = NULL; unsigned longSize = 0; struct dyString *errors = newDyString(1024); (void) bbiBriefMeasure(tdbEl->type, bigDataUrl, bigDataIndex, &chromCount, &itemCount, errors, &longName, &longSize); chromSize = longSize; chromName = longName; } } if (tdbIsCompositeView(tdbEl)) hPrintf("<li><b>%s</b>: %s : composite view of parent: %s</li>\n", tdbEl->track, tdbEl->type, tdbEl->parent->track); else { if (isSupportedType(tdbEl->type)) - hubSampleUrl(hub, tdbEl, chromCount, itemCount, chromName, chromSize, genome, errorString); + hubSampleUrl(hub, tdbEl, chromCount, itemCount, genome, errorString); else hPrintf("<li><b>%s</b>: %s : subtrack of parent: %s</li>\n", tdbEl->track, tdbEl->type, tdbEl->parent->track); } hashCountTrack(tdbEl, countTracks); if (tdbEl->subtracks) hubSubTracks(hub, db, tdbEl, countTracks, chromCount, itemCount, chromName, chromSize, genome, errorString); } } hPrintf(" </ul></li>\n"); } /* hubSubTracks() */ static void showSubTracks(struct trackHub *hub, char *db, struct trackDb *tdb, struct hash *countTracks, char *chromName, unsigned chromSize, char *errorString) /* tdb has subtracks, show only subTracks, no details */ { hPrintf(" <li><ul>\n"); if (debug) hPrintf(" <li>subtracks for '%s' db: '%s'</li>\n", tdb->track, db); if (tdb->subtracks) { struct trackDb *tdbEl = NULL; for (tdbEl = tdb->subtracks; tdbEl; tdbEl = tdbEl->next) { if (tdbIsCompositeView(tdbEl)) hPrintf("<li><b>%s</b>: %s : composite view of parent: %s</li>\n", tdbEl->track, tdbEl->type, tdbEl->parent->track); else { if (isSupportedType(tdbEl->type)) - sampleUrl(hub, db, tdbEl, chromName, chromSize, errorString); + sampleUrl(hub, db, tdbEl, errorString); else hPrintf("<li><b>%s</b>: %s : subtrack of parent: %s</li>\n", tdbEl->track, tdbEl->type, tdbEl->parent->track); } hashCountTrack(tdbEl, countTracks); if (tdbEl->subtracks) showSubTracks(hub, db, tdbEl, countTracks, chromName, chromSize, errorString); } } hPrintf(" </ul></li>\n"); } static void trackSettings(struct trackDb *tdb, struct hash *countTracks) /* process the settingsHash for a trackDb, recursive when subtracks */ { hPrintf(" <li><ul>\n"); @@ -592,57 +580,57 @@ if (! (compositeContainer || compositeView) ) { if (chromSize < 1 || depthSearch) { char *longName = NULL; unsigned longSize = 0; (void) bbiBriefMeasure(tdb->type, bigDataUrl, bigDataIndex, &chromCount, &itemCount, errors, &longName, &longSize); chromSize = longSize; chromName = longName; } } if (depthSearch && bigDataUrl) { if (isSupportedType(tdb->type)) - hubSampleUrl(hub, tdb, chromCount, itemCount, chromName, chromSize, genome, errors->string); + hubSampleUrl(hub, tdb, chromCount, itemCount, genome, errors->string); } else { if (compositeContainer) hPrintf(" <li><b>%s</b>: %s : composite track container has %d subtracks</li>\n", tdb->track, tdb->type, slCount(tdb->subtracks)); else if (compositeView) hPrintf(" <li><b>%s</b>: %s : composite view of parent: %s</li>\n", tdb->track, tdb->type, tdb->parent->track); else if (superChild) { if (isSupportedType(tdb->type)) - hubSampleUrl(hub, tdb, chromCount, itemCount, chromName, chromSize, genome, errors->string); + hubSampleUrl(hub, tdb, chromCount, itemCount, genome, errors->string); else hPrintf(" <li><b>%s</b>: %s : superTrack child of parent: %s</li>\n", tdb->track, tdb->type, tdb->parent->track); } else if (! depthSearch && bigDataUrl) { if (isSupportedType(tdb->type)) { - hubSampleUrl(hub, tdb, chromCount, itemCount, chromName, chromSize, genome, errors->string); + hubSampleUrl(hub, tdb, chromCount, itemCount, genome, errors->string); } } else { if (isSupportedType(tdb->type)) { - hubSampleUrl(hub, tdb, chromCount, itemCount, chromName, chromSize, genome, errors->string); + hubSampleUrl(hub, tdb, chromCount, itemCount, genome, errors->string); } else hPrintf(" <li><b>%s</b>: %s (what is this)</li>\n", tdb->track, tdb->type); } } if (allTrackSettings) { hPrintf(" <li><ul>\n"); trackSettings(tdb, countTracks); /* show all settings */ hPrintf(" </ul></li>\n"); } else if (tdb->subtracks) { hubSubTracks(hub, db, tdb, countTracks, chromCount, itemCount, chromName, chromSize, genome, errors->string); } @@ -660,40 +648,40 @@ { char *bigDataUrl = trackDbSetting(tdb, "bigDataUrl"); boolean compositeContainer = tdbIsComposite(tdb); boolean compositeView = tdbIsCompositeView(tdb); boolean superChild = tdbIsSuperTrackChild(tdb); boolean depthSearch = cartUsualBoolean(cart, "depthSearch", FALSE); hashCountTrack(tdb, countTracks); if (compositeContainer) hPrintf(" <li><b>%s</b>: %s : composite track container has %d subtracks</li>\n", tdb->track, tdb->type, slCount(tdb->subtracks)); else if (compositeView) hPrintf(" <li><b>%s</b>: %s : composite view of parent: %s</li>\n", tdb->track, tdb->type, tdb->parent->track); else if (superChild) { if (isSupportedType(tdb->type)) - sampleUrl(NULL, db, tdb, chromName, chromSize, errorString); + sampleUrl(NULL, db, tdb, errorString); else hPrintf(" <li><b>%s</b>: %s : superTrack child of parent: %s</li>\n", tdb->track, tdb->type, tdb->parent->track); } else if (! depthSearch && bigDataUrl) hPrintf(" <li><b>%s</b>: %s : %s</li>\n", tdb->track, tdb->type, bigDataUrl); else { if (isSupportedType(tdb->type)) - sampleUrl(NULL, db, tdb, chromName, chromSize, errorString); + sampleUrl(NULL, db, tdb, errorString); else hPrintf(" <li><b>%s</b>: %s</li>\n", tdb->track, tdb->type); } if (allTrackSettings) { hPrintf(" <li><ul>\n"); trackSettings(tdb, countTracks); /* show all settings */ hPrintf(" </ul></li>\n"); } else if (tdb->subtracks) { showSubTracks(NULL, db, tdb, countTracks, chromName, chromSize, NULL); } return; @@ -1226,81 +1214,35 @@ 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"); } -static void doMiddle(struct cart *theCart) -/* Set up globals and make web page */ +static void apiRequest(char *pathInfo) { -cart = theCart; -measureTiming = isNotEmpty(cartOptionalString(cart, "measureTiming")); -char *database = NULL; -char *genome = NULL; - -if (measureTiming) - startProcessTiming(); - -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); -// debug = TRUE; - -int timeout = cartUsualInt(cart, "udcTimeout", 300); -if (udcCacheTimeout() < timeout) - udcSetCacheTimeout(timeout); -knetUdcInstall(); - -char *pathInfo = getenv("PATH_INFO"); -/* nothing on incoming path, then display the WEB page instead */ -if (sameOk("/",pathInfo)) - pathInfo = NULL; - -boolean commandError = FALSE; +hPrintDisable(); /*expect no more than MAX_PATH_INFO number of words*/ char *words[MAX_PATH_INFO]; - -if (isNotEmpty(pathInfo)) - { /* can immediately verify valid parameters right here right now */ char *start = cgiOptionalString("start"); char *end = cgiOptionalString("end"); char *db = cgiOptionalString("db"); struct dyString *errorMsg = newDyString(128); if (isNotEmpty(db)) { struct sqlConnection *conn = hAllocConnMaybe(db); if (NULL == conn) dyStringPrintf(errorMsg, "can not find database db='%s' for endpoint '%s'", db, pathInfo); else hFreeConn(&conn); } if (isNotEmpty(start) || isNotEmpty(end)) @@ -1341,31 +1283,57 @@ if (isNotEmpty(errorMsg->string)) apiErrAbort(err400, err400Msg, "%s", errorMsg->string); setupFunctionHash(); struct hashEl *hel = parsePathInfo(pathInfo, words); /* verify valid API command */ if (hel) /* have valid command */ { hPrintDisable(); void (*apiFunction)(char **) = hel->val; (*apiFunction)(words); return; } else apiErrAbort(err400, err400Msg, "no such command: '/%s/%s for endpoint '%s'", words[0], words[1], pathInfo); - } +} /* static void apiRequest(char *pathInfo) */ + +static void doMiddle(struct cart *theCart) +/* Set up globals and make web page */ +{ +cart = theCart; +// measureTiming = isNotEmpty(cartOptionalString(cart, "measureTiming")); +char *database = NULL; +char *genome = NULL; + +if (measureTiming) + startProcessTiming(); + +cgiVarSet("ignoreCookie", "1"); + +getDbAndGenome(cart, &database, &genome, oldVars); +initGenbankTableNames(database); +initSupportedTypes(); +initUrlPrefix(); + +trackLeavesOnly = cartUsualBoolean(cart, "trackLeavesOnly", trackLeavesOnly); +jsonOutputArrays = cartUsualBoolean(cart, "jsonOutputArrays", jsonOutputArrays); + +char *pathInfo = getenv("PATH_INFO"); +/* nothing on incoming path, then display the WEB page instead */ +if (sameOk("/",pathInfo)) + pathInfo = NULL; (void) hubPublicDbLoadAll(); webStartJWest(cart, database, "UCSC JSON API interface"); // webStartGbNoBanner(cart, database, "UCSC JSON API interface"); // webStartGbOptionalBanner(cart, database, "UCSC JSON API interface", TRUE, FALSE); hPrintf("<div class='container-fluid gbPage'>\n"); /* these style mentions need to go into custom css file */ hPrintf("<div style='border:10px solid white'>\n"); if (debug) { hPrintf("<ul>\n"); hPrintf("<li>hgBotDelay: %d</li>\n", botDelay); @@ -1409,35 +1377,30 @@ { hPrintf("<ul>\n"); hPrintf("<li>otherHubUrl: '%s'</li>\n", otherHubUrl); hPrintf("<li>hubDropDown: '%s'</li>\n", hubDropDown); hPrintf("<li>urlDropDown: '%s'</li>\n", urlDropDown); hPrintf("<li>ucscDb: '%s'</li>\n", ucscDb); hPrintf("<li>urlInput: '%s'</li>\n", urlInput); hPrintf("</ul>\n"); } if (isEmpty(otherHubUrl)) otherHubUrl = urlInput; if (sameWord(RADIO_OTHERHUB, selectRadio)) /* requested other hub URL */ urlInput = otherHubUrl; -if (commandError) - { - hPrintf("<h3>ERROR: no such command: '%s/%s' for endpoint '%s'</h3>", words[0], words[1], pathInfo); - } - long lastTime = clock1000(); struct trackHub *hub = errCatchTrackHubOpen(urlInput); if (measureTiming) { long thisTime = clock1000(); hPrintf("<em>hub open time: %ld millis</em><br>\n", thisTime - lastTime); } hPrintf("<h3>Documentation: <a href='../../goldenPath/help/api.html'>API definitions/help</a>, and <a href='../../goldenPath/help/trackDb/trackDbHub.html' target=_blank>Track definition document</a> for definitions of track settings.</h3>\n"); if (debug) showCartDump(); hPrintf("<h2>Explore hub or database assemblies and tracks</h2>\n"); @@ -1473,42 +1436,99 @@ if (timedOut) hPrintf("<h1>Reached time out %ld seconds</h1>", timeOutSeconds); if (measureTiming) hPrintf("<em>Overall total time: %ld millis</em><br>\n", clock1000() - enteredMainTime); hPrintf("</div> <!-- end of text analysis output -->\n"); hPrintf("</div> <!-- end of surrounding border-->\n"); hPrintf("</div> <!-- end this page contents -->\n"); webIncludeFile("inc/jWestFooter.html"); webEndJWest(); // cartWebEnd(); } /* void doMiddle(struct cart *theCart) */ +static void setGlobalCgiVars() +/* check for CGI variables and set global flags */ +{ +char *trackLeaves = cgiOptionalString("trackLeavesOnly"); +if (sameOk("1", trackLeaves)) + trackLeavesOnly = TRUE; + +char *jsonArray = cgiOptionalString("jsonOutputArrays"); +if (sameOk("1", jsonArray)) + jsonOutputArrays = TRUE; + +int maybeDebug = cgiOptionalInt("debug", 0); +if (1 == maybeDebug) + debug = TRUE; + +char *measTime = cgiOptionalString("measureTiming"); +if (isNotEmpty(measTime) && sameWord("1", measTime)) + measureTiming = TRUE; +char *maxOut = cgiOptionalString("maxItemsOutput"); +if (isNotEmpty(maxOut)) + { + long long n = -2; + struct errCatch *errCatch = errCatchNew(); + if (errCatchStart(errCatch)) + { + n = sqlLongLong(maxOut); + } + errCatchEnd(errCatch); + if (errCatch->gotError) + apiErrAbort(err400, err400Msg, "can not recognize maxItemsOutput '%s' as a number", maxOut); + else + { + if (n == -1) /* can use -1 to indicate as much as allowed */ + maxItemsOutput = maxItemLimit; + else if (n > maxItemLimit) /* safety check */ + apiErrAbort(err400, err400Msg, "requested maxItemsOutput '%s' greater than maximum limit allowed: %d", maxOut, maxItemLimit); + else if (n < 1) + apiErrAbort(err400, err400Msg, "requested maxItemsOutput '%s' can not be less than one", maxOut, maxItemLimit); + else + maxItemsOutput = n; + } + } +} /* static void setGlobalCgiVars() */ + /* Null terminated list of CGI Variables we don't want to save * permanently. */ static char *excludeVars[] = {"Submit", "submit", "sourceSelected", "selectRadio", "ucscGenome", "publicHubs", "clade", NULL,}; int main(int argc, char *argv[]) /* Process command line. */ { enteredMainTime = clock1000(); cgiSpoof(&argc, argv); verboseTimeInit(); /* similar delay system as in DAS server */ botDelay = hgBotDelayTimeFrac(delayFraction); if (botDelay > 0) { if (botDelay > 2000) { hogExit(); return 0; } sleep1000(botDelay); } +setGlobalCgiVars(); + +int timeout = cgiOptionalInt("udcTimeout", 300); +if (udcCacheTimeout() < timeout) + udcSetCacheTimeout(timeout); +knetUdcInstall(); + +char *pathInfo = getenv("PATH_INFO"); +if (isNotEmpty(pathInfo)) /* can get to this immediately, no cart needed */ + apiRequest(pathInfo); +else + { trackCounter = hashNew(0); cartEmptyShellNoContent(doMiddle, hUserCookie(), excludeVars, oldVars); + } cgiExitTime("hubApi", enteredMainTime); return 0; }