09b542fe035a233ec45d2092e4a0ab38e99c3e32 hiram Mon Feb 11 09:50:37 2019 -0800 adding dataTime and dataTimeStamp to the outputs refs #18869 diff --git src/hg/hubApi/hubApi.c src/hg/hubApi/hubApi.c index 2f75c10..d9b8178 100644 --- src/hg/hubApi/hubApi.c +++ src/hg/hubApi/hubApi.c @@ -88,31 +88,31 @@ freeMem(a); } static void jsonTagValue(FILE *f, char *tag, char *value) /* output one json string: "tag":"value" appropriately quoted and encoded */ { fprintf(f,"\"%s\":",tag); jsonStringPrint(f, value); } static struct jsonWrite *jsonStartOutput() /* begin json output */ { struct jsonWrite *jw = jsonWriteNew(); jsonWriteObjectStart(jw, NULL); -jsonWriteString(jw, "version", "0.1"); +jsonWriteString(jw, "apiVersion", "0.1"); jsonWriteString(jw, "source", "UCSantaCruz"); return jw; } static void jsonErrAbort(char *format, ...) /* Issue an error message in json format. */ { char errMsg[2048]; va_list args; va_start(args, format); vsnprintf(errMsg, sizeof(errMsg), format, args); fputc('{',stdout); jsonTagValue(stdout, "error", errMsg); fputc('}',stdout); } @@ -478,30 +478,34 @@ hPrintf("
  • %ld total tracks counted, %d different track types:
  • \n", totalTracks, trackCounter->elCount); hPrintf(" \n"); } hPrintf("\n"); return retList; } /* static struct slName *genomeList () */ static char *urlFromShortLabel(char *shortLabel) +/* this is not a fair way to get the URL since shortLabel's are not + * necessarily unique. This is temporary. TBD: need to always use URL + * and then get the shortLabel + */ { char hubUrl[1024]; char query[1024]; struct sqlConnection *conn = hConnectCentral(); // Build a query to select the hubUrl for the given shortLabel sqlSafef(query, sizeof(query), "select hubUrl from %s where shortLabel='%s'", hubPublicTableName(), shortLabel); if (! sqlQuickQuery(conn, query, hubUrl, sizeof(hubUrl))) hubUrl[0] = 0; hDisconnectCentral(&conn); return cloneString(hubUrl); } static void dbDbJsonData(struct jsonWrite *jw, struct dbDb *el) /* Print out dbDb table element in JSON format. @@ -544,32 +548,39 @@ { jsonErrAbort("ERROR: can not 'desc' table '%s'\n", table); return TRUE; } while ((row = sqlNextRow(sr)) != NULL) jsonWriteString(jw, NULL, row[0]); sqlFreeResult(&sr); hDisconnectCentral(&conn); jsonWriteListEnd(jw); return FALSE; } static void jsonPublicHubs() /* output the hubPublic SQL table */ { +struct sqlConnection *conn = hConnectCentral(); +char *dataTime = sqlTableUpdate(conn, hubPublicTableName()); +hDisconnectCentral(&conn); +time_t dataTimeStamp = sqlDateToUnixTime(dataTime); struct hubPublic *el = publicHubList; struct jsonWrite *jw = jsonStartOutput(); +jsonWriteString(jw, "dataTime", dataTime); +jsonWriteNumber(jw, "dataTimeStamp", (long long)dataTimeStamp); +freeMem(dataTime); tableColumns(jw, hubPublicTableName()); jsonWriteListStart(jw, "publicHubData"); for ( ; el != NULL; el = el->next ) { hubPublicJsonData(jw, el); } jsonWriteListEnd(jw); jsonWriteObjectEnd(jw); fputs(jw->dy->string,stdout); } static int dbDbCmpName(const void *va, const void *vb) /* Compare two dbDb elements: name, ignore case. */ { const struct dbDb *a = *((struct dbDb **)va); @@ -588,136 +599,162 @@ char **row; while ((row = sqlNextRow(sr)) != NULL) { el = dbDbLoad(row); slAddHead(&dbList, el); } sqlFreeResult(&sr); hDisconnectCentral(&conn); slSort(&dbList, dbDbCmpName); return dbList; } static void jsonDbDb() /* output the dbDb SQL table */ { +struct sqlConnection *conn = hConnectCentral(); +char *dataTime = sqlTableUpdate(conn, "dbDb"); +hDisconnectCentral(&conn); +time_t dataTimeStamp = sqlDateToUnixTime(dataTime); struct dbDb *dbList = ucscDbDb(); struct dbDb *el; struct jsonWrite *jw = jsonStartOutput(); +jsonWriteString(jw, "dataTime", dataTime); +jsonWriteNumber(jw, "dataTimeStamp", (long long)dataTimeStamp); +freeMem(dataTime); tableColumns(jw, "dbDb"); jsonWriteListStart(jw, "ucscGenomes"); for ( el=dbList; el != NULL; el = el->next ) { dbDbJsonData(jw, el); } jsonWriteListEnd(jw); jsonWriteObjectEnd(jw); fputs(jw->dy->string,stdout); } static void chromInfoJsonOutput(FILE *f, char *db) /* for given db, if there is a track, list the chromosomes in that track, * for no track, simply list the chromosomes in the sequence */ { -char *track = cgiOptionalString("track"); -if (track) - { +char *table = cgiOptionalString("track"); struct sqlConnection *conn = hAllocConn(db); - if (! sqlTableExists(conn, track)) - jsonErrAbort("ERROR: endpoint: /list/chromosomes?db=%&table=%s ERROR table does not exist", db, track); - if (sqlColumnExists(conn, track, "chrom")) +/* in trackDb language: track == table */ +if (table) { + if (! sqlTableExists(conn, table)) + jsonErrAbort("ERROR: endpoint: /list/chromosomes?db=%&table=%s ERROR table does not exist", db, table); + if (sqlColumnExists(conn, table, "chrom")) + { + char *dataTime = sqlTableUpdate(conn, table); + time_t dataTimeStamp = sqlDateToUnixTime(dataTime); struct jsonWrite *jw = jsonStartOutput(); jsonWriteString(jw, "genome", db); - jsonWriteString(jw, "track", track); + jsonWriteString(jw, "track", table); + jsonWriteString(jw, "dataTime", dataTime); + jsonWriteNumber(jw, "dataTimeStamp", (long long)dataTimeStamp); + freeMem(dataTime); struct slPair *list = NULL; char query[2048]; - sqlSafef(query, sizeof(query), "select distinct chrom from %s", track); + sqlSafef(query, sizeof(query), "select distinct chrom from %s", table); struct sqlResult *sr = sqlGetResult(conn, query); char **row; while ((row = sqlNextRow(sr)) != NULL) { int size = hChromSize(db, row[0]); slAddHead(&list, slPairNew(row[0], intToPt(size))); } sqlFreeResult(&sr); slPairIntSort(&list); slReverse(&list); jsonWriteNumber(jw, "chromCount", (long long)slCount(list)); jsonWriteObjectStart(jw, "chromosomes"); struct slPair *el = list; for ( ; el != NULL; el = el->next ) jsonWriteNumber(jw, el->name, (long long)ptToInt(el->val)); jsonWriteObjectEnd(jw); /* chromosomes */ jsonWriteObjectEnd(jw); /* top level */ fputs(jw->dy->string,stdout); } else { - jsonErrAbort("ERROR: table '%s' is not a position table, no chromosomes for genome: '%s'", track, db); + jsonErrAbort("ERROR: table '%s' is not a position table, no chromosomes for genome: '%s'", table, db); } - hFreeConn(&conn); } else { + char *dataTime = sqlTableUpdate(conn, "chromInfo"); + time_t dataTimeStamp = sqlDateToUnixTime(dataTime); struct chromInfo *ciList = createChromInfoList(NULL, db); struct chromInfo *el = ciList; struct jsonWrite *jw = jsonStartOutput(); jsonWriteString(jw, "genome", db); + jsonWriteString(jw, "dataTime", dataTime); + 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 */ jsonWriteObjectEnd(jw); /* top level */ fputs(jw->dy->string,stdout); } +hFreeConn(&conn); } static void trackDbJsonOutput(char *db, FILE *f) /* return track list from specified UCSC database name */ { +struct sqlConnection *conn = hAllocConn(db); +char *dataTime = sqlTableUpdate(conn, "trackDb"); +time_t dataTimeStamp = sqlDateToUnixTime(dataTime); +hFreeConn(&conn); struct trackDb *tdbList = hTrackDb(db); struct trackDb *el; struct jsonWrite *jw = jsonStartOutput(); jsonWriteString(jw, "db", db); +jsonWriteString(jw, "dataTime", dataTime); +jsonWriteNumber(jw, "dataTimeStamp", (long long)dataTimeStamp); +freeMem(dataTime); jsonWriteListStart(jw, "tracks"); for (el = tdbList; el != NULL; el = el->next ) jsonWriteString(jw, NULL, el->track); jsonWriteListEnd(jw); jsonWriteObjectEnd(jw); fputs(jw->dy->string,stdout); } /* static void trackDbJsonOutput(char *db, FILE *f) */ #define MAX_PATH_INFO 32 static 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 *hubUrl = cgiOptionalString("hubUrl"); if (isEmpty(hubUrl)) jsonErrAbort("ERROR: must supply hubUrl='http:...' some URL to a hub for /list/genomes\n"); struct trackHub *hub = trackHubOpen(hubUrl, ""); +registrationTime if (hub->genomeList) { struct jsonWrite *jw = jsonStartOutput(); jsonWriteString(jw, "hubUrl", hubUrl); jsonWriteListStart(jw, "genomes"); struct slName *theList = genomeList(hub, NULL, NULL); slNameSort(&theList); struct slName *el = theList; for ( ; el ; el = el->next ) { jsonWriteString(jw, NULL, el->name); } jsonWriteListEnd(jw); jsonWriteObjectEnd(jw); fputs(jw->dy->string,stdout); @@ -794,30 +831,31 @@ static void apiFunctionSwitch(char *pathInfo) /* given a pathInfo string: /command/subCommand/etc... * parse that and decide on which function to acll */ { hPrintDisable(); /* turn off all normal HTML output, doing JSON output */ /* the leading slash has been removed from the pathInfo, therefore, the * chop will have the first word in words[0] */ char *words[MAX_PATH_INFO];/*expect no more than MAX_PATH_INFO number of words*/ int wordCount = chopByChar(pathInfo, '/', words, ArraySize(words)); if (wordCount < 2) jsonErrAbort("ERROR: no endpoint commands found ?\n"); +/* TBD: need to protect this hash find from 'not found' error */ void (*apiFunction)(char **) = hashMustFindVal(apiFunctionHash, words[0]); (*apiFunction)(words); } /* static void apiFunctionSwitch(char *pathInfo) */ static void tracksForUcscDb(char * ucscDb) { hPrintf("

    Tracks in UCSC genome: '%s'
    \n", ucscDb); struct trackDb *tdbList = hTrackDb(ucscDb); struct trackDb *track; hPrintf("