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");
struct hashEl *hel;
struct hashCookie hc = hashFirst(trackCounter);
while ((hel = hashNext(&hc)) != NULL)
{
hPrintf(" - %d - %s - total
\n", ptToInt(hel->val), hel->name);
}
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("
\n");
for (track = tdbList; track != NULL; track = track->next )
{
hPrintf("- %s
\n", track->track);