af113249f30db748bae4c4c79cc270c548eb46d4 hiram Tue May 14 14:13:29 2019 -0700 now providing an itemCount for each track in the list tracks function refs #18869 diff --git src/hg/hubApi/list.c src/hg/hubApi/list.c index 292d80e..bf4b9fb 100644 --- src/hg/hubApi/list.c +++ src/hg/hubApi/list.c @@ -321,110 +321,179 @@ jsonWriteString(jw, "track", table); jsonWriteNumber(jw, "dataTimeStamp", (long long)dataTimeStamp); freeMem(dataTime); jsonWriteNumber(jw, "chromCount", (long long)slCount(ciList)); jsonWriteObjectStart(jw, "chromosomes"); for ( ; el != NULL; el = el->next ) { jsonWriteNumber(jw, el->chrom, (long long)el->size); } jsonWriteObjectEnd(jw); /* chromosomes */ apiFinishOutput(0, NULL, jw); } hFreeConn(&conn); } -static void recursiveTrackList(struct jsonWrite *jw, struct trackDb *tdb) +static long long bbiItemCount(char *bigDataUrl, char *type) +/* check the bigDataUrl to see what the itemCount is there */ +{ +long long itemCount = 0; +struct errCatch *errCatch = errCatchNew(); +if (errCatchStart(errCatch)) + { + if (allowedBigBedType(type)) + { + struct bbiFile *bbi = NULL; + bbi = bigBedFileOpen(bigDataUrl); + itemCount = bigBedItemCount(bbi); + bbiFileClose(&bbi); + } + else if (startsWithWord("bigWig", type)) + { + struct bbiFile *bwf = bigWigFileOpen(bigDataUrl); + struct bbiSummaryElement sum = bbiTotalSummary(bwf); + itemCount = sum.validCount; + bbiFileClose(&bwf); + } + } +errCatchEnd(errCatch); +errCatchFree(&errCatch); +return itemCount; +} + +static long long dataItemCount(char *db, struct trackDb *tdb) +/* determine how many items are in this data set */ +{ +boolean isContainer = tdbIsComposite(tdb) || tdbIsCompositeView(tdb); +if (trackDbSetting(tdb, "container")) + isContainer = TRUE; +long long itemCount = 0; +if (isContainer) /* containers have no data items */ + return itemCount; +if (sameWord("downloadsOnly", tdb->type)) + return itemCount; + +char *bigDataUrl = trackDbSetting(tdb, "bigDataUrl"); +if (isNotEmpty(bigDataUrl)) + itemCount = bbiItemCount(bigDataUrl, tdb->type); +else + { + /* prepare for getting table row count, find table name */ + /* the trackDb might have a specific table defined */ + char *tableName = trackDbSetting(tdb, "table"); + if (isEmpty(tableName)) + tableName = trackDbSetting(tdb, "track"); + if (isNotEmpty(tableName)) + { + struct sqlConnection *conn = hAllocConnMaybe(db); + if (conn) + { + char query[2048]; + sqlSafef(query, sizeof(query), "select count(*) from %s", tableName); + itemCount = sqlQuickNum(conn, query); + hFreeConn(&conn); + } + } + } +return itemCount; +} + +static void recursiveTrackList(struct jsonWrite *jw, struct trackDb *tdb, + char *db) /* output trackDb tags only for real tracks, not containers, * recursive when subtracks exist */ { boolean isContainer = tdbIsComposite(tdb) || tdbIsCompositeView(tdb); /* do *NOT* print containers when 'trackLeavesOnly' requested */ if (! (trackLeavesOnly && isContainer) ) { + boolean protectedData = FALSE; + long long itemCount = 0; + if (trackDbSetting(tdb, "tableBrowser")) + protectedData = TRUE; + else + itemCount = dataItemCount(db, tdb); jsonWriteObjectStart(jw, tdb->track); if (tdbIsComposite(tdb)) jsonWriteString(jw, "compositeContainer", "TRUE"); if (tdbIsCompositeView(tdb)) jsonWriteString(jw, "compositeViewContainer", "TRUE"); jsonWriteString(jw, "shortLabel", tdb->shortLabel); jsonWriteString(jw, "type", tdb->type); jsonWriteString(jw, "longLabel", tdb->longLabel); + jsonWriteNumber(jw, "itemCount", itemCount); if (tdb->parent) jsonWriteString(jw, "parent", tdb->parent->track); if (tdb->settingsHash) { - boolean protectedData = FALSE; - if (trackDbSetting(tdb, "tableBrowser")) - protectedData = TRUE; struct hashEl *hel; struct hashCookie hc = hashFirst(tdb->settingsHash); while ((hel = hashNext(&hc)) != NULL) { if (sameWord("track", hel->name)) continue; // already output in header if (sameWord("tableBrowser", hel->name)) jsonWriteBoolean(jw, "protectedData", TRUE); else if (isEmpty((char *)hel->val)) jsonWriteString(jw, hel->name, "empty"); else if (protectedData && sameWord(hel->name, "bigDataUrl")) jsonWriteString(jw, hel->name, "protectedData"); else jsonWriteString(jw, hel->name, (char *)hel->val); } } if (tdb->subtracks) { struct trackDb *el = NULL; for (el = tdb->subtracks; el != NULL; el = el->next ) - recursiveTrackList(jw, el); + recursiveTrackList(jw, el, db); } jsonWriteObjectEnd(jw); } else if (tdb->subtracks) { struct trackDb *el = NULL; for (el = tdb->subtracks; el != NULL; el = el->next ) - recursiveTrackList(jw, el); + recursiveTrackList(jw, el, db); } } /* static void recursiveTrackList() */ static void trackDbJsonOutput(char *db, FILE *f) /* return track list from specified UCSC database name */ { struct sqlConnection *conn = hAllocConnMaybe(db); if (NULL == conn) apiErrAbort(err400, err400Msg, "can not find 'genome=%s' for endpoint '/list/tracks", db); char *dataTime = sqlTableUpdate(conn, "trackDb"); time_t dataTimeStamp = sqlDateToUnixTime(dataTime); replaceChar(dataTime, ' ', 'T'); /* ISO 8601 */ hFreeConn(&conn); struct trackDb *tdbList = obtainTdb(NULL, db); struct jsonWrite *jw = apiStartOutput(); jsonWriteString(jw, "genome", db); jsonWriteString(jw, "dataTime", dataTime); jsonWriteNumber(jw, "dataTimeStamp", (long long)dataTimeStamp); freeMem(dataTime); struct trackDb *el = NULL; for (el = tdbList; el != NULL; el = el->next ) { - recursiveTrackList(jw, el); + recursiveTrackList(jw, el, db); } apiFinishOutput(0, NULL, jw); } /* static void trackDbJsonOutput(char *db, FILE *f) */ void apiList(char *words[MAX_PATH_INFO]) /* 'list' function words[1] is the subCommand */ { if (sameWord("publicHubs", words[1])) jsonPublicHubs(); else if (sameWord("ucscGenomes", words[1])) jsonDbDb(); else if (sameWord("hubGenomes", words[1])) { char *extraArgs = verifyLegalArgs(argsListHubGenomes); /* only one allowed */ if (extraArgs) @@ -487,31 +556,31 @@ if (isEmpty(genome)) apiErrAbort(err400, err400Msg, "must supply genome='someName' the name of a genome in a hub for /list/tracks\n"); if (isEmpty(hubUrl)) apiErrAbort(err400, err400Msg, "must supply hubUrl='http:...' some URL to a hub for /list/tracks"); } struct trackHub *hub = errCatchTrackHubOpen(hubUrl); struct trackHubGenome *hubGenome = findHubGenome(hub, genome, "/list/tracks", hubUrl); struct trackDb *tdbList = obtainTdb(hubGenome, NULL); struct jsonWrite *jw = apiStartOutput(); jsonWriteString(jw, "hubUrl", hubUrl); jsonWriteObjectStart(jw, hubGenome->name); struct trackDb *el = NULL; for (el = tdbList; el != NULL; el = el->next ) { - recursiveTrackList(jw, el); + recursiveTrackList(jw, el, db); } jsonWriteObjectEnd(jw); apiFinishOutput(0, NULL, jw); } else if (sameWord("chromosomes", words[1])) { char *extraArgs = verifyLegalArgs(argsListChromosomes); if (extraArgs) apiErrAbort(err400, err400Msg, "extraneous arguments found for function /list/chromosomes '%s'", extraArgs); char *hubUrl = cgiOptionalString("hubUrl"); char *genome = cgiOptionalString("genome"); char *db = cgiOptionalString("genome"); if (isEmpty(hubUrl) && isNotEmpty(db)) {