9661f8ba9e015aef34e09240d677ac7978ec0766 braney Wed May 18 12:33:41 2011 -0700 move hub connection stuff into hg/lib so hgTracks can add hubs on its own diff --git src/hg/lib/hubConnect.c src/hg/lib/hubConnect.c index 7138135..3f20fd8 100644 --- src/hg/lib/hubConnect.c +++ src/hg/lib/hubConnect.c @@ -3,30 +3,32 @@ * hub symbolic names and hub URLs, to see if a hub is up or down or sideways (up but badly * formatted) etc. Note that there is no C structure corresponding to a row in the hubConnect * table by design. We just want field-by-field access to this. */ #include "common.h" #include "linefile.h" #include "hash.h" #include "dystring.h" #include "sqlNum.h" #include "jksql.h" #include "hdb.h" #include "net.h" #include "trackHub.h" #include "hubConnect.h" #include "hui.h" +#include "errCatch.h" +#include "obscure.h" boolean isHubTrack(char *trackName) /* Return TRUE if it's a hub track. */ { return startsWith(hubTrackPrefix, trackName); } boolean hubConnectTableExists() /* Return TRUE if the hubConnect table exists. */ { struct sqlConnection *conn = hConnectCentral(); boolean exists = sqlTableExists(conn, hubPublicTableName); hDisconnectCentral(&conn); return exists; @@ -162,32 +164,41 @@ if (hub != NULL) { slAddHead(&hubList, hub); } } slFreeList(&nameList); hDisconnectCentral(&conn); slReverse(&hubList); return hubList; } int hubIdFromTrackName(char *trackName) /* Given something like "hub_123_myWig" return 123 */ { assert(startsWith("hub_", trackName)); -trackName += 4; -return sqlUnsigned(trackName); +char *ptr1 = trackName; +ptr1 += 4; +char *ptr2 = strchr(ptr1, '_'); + +if (ptr2 == NULL) + errAbort("hub track %s not in correct format\n", trackName); +char save = *ptr2; +*ptr2 = 0; +unsigned val = sqlUnsigned(ptr1); +*ptr2 = save; +return val; } char *hubConnectSkipHubPrefix(char *trackName) /* Given something like "hub_123_myWig" return myWig. Don't free this, it's not allocated */ { assert(startsWith("hub_", trackName)); trackName += 4; trackName = strchr(trackName, '_'); assert(trackName != NULL); return trackName + 1; } struct trackHub *trackHubFromId(struct cart *cart, unsigned hubId) /* Given a hub ID number, return corresponding trackHub structure. * ErrAbort if there's a problem. */ @@ -262,15 +273,210 @@ for (parent = tdb; parent != NULL; parent = parent->parent) { char *simpleName = hubConnectSkipHubPrefix(tdb->track); char *url = trackHubRelativeUrl(hubGenome->trackDbFile, simpleName); char buffer[10*1024]; safef(buffer, sizeof buffer, "%s.html", url); parent->html = netReadTextFileIfExists(buffer); freez(&url); } trackHubClose(&hub); return tdb; } +static void enterHubInStatus(struct trackHub *tHub, boolean unlisted) +/* put the hub status in the hubStatus table */ +{ +struct sqlConnection *conn = hConnectCentral(); + +/* calculate dbList */ +struct dyString *dy = newDyString(1024); +struct hashEl *hel; +struct hashCookie cookie = hashFirst(tHub->genomeHash); +int dbCount = 0; + +while ((hel = hashNext(&cookie)) != NULL) + { + dbCount++; + dyStringPrintf(dy,"%s,", hel->name); + } + + +char query[512]; +safef(query, sizeof(query), "insert into %s (hubUrl,status,shortLabel, longLabel, dbList, dbCount) values (\"%s\",%d,\"%s\",\"%s\", \"%s\", %d)", + hubStatusTableName, tHub->url, unlisted ? 1 : 0, + tHub->shortLabel, tHub->longLabel, + dy->string, dbCount); +sqlUpdate(conn, query); +hDisconnectCentral(&conn); +} + +static unsigned getHubId(char *url, char **errorMessage) +/* find id for url in hubStatus table */ +{ +struct sqlConnection *conn = hConnectCentral(); +char query[512]; +char **row; +boolean foundOne = FALSE; +int id = 0; + +safef(query, sizeof(query), "select id,errorMessage from %s where hubUrl = \"%s\"", hubStatusTableName, url); + +struct sqlResult *sr = sqlGetResult(conn, query); + +while ((row = sqlNextRow(sr)) != NULL) + { + if (foundOne) + errAbort("more than one line in %s with hubUrl %s\n", + hubStatusTableName, url); + + foundOne = TRUE; + + char *thisId = row[0], *thisError = row[1]; + + if (!isEmpty(thisError)) + *errorMessage = cloneString(thisError); + + id = sqlUnsigned(thisId); + } +sqlFreeResult(&sr); + +hDisconnectCentral(&conn); + +return id; +} + +static boolean hubHasDatabase(unsigned id, char *database) +/* check to see if hub specified by id supports database */ +{ +struct sqlConnection *conn = hConnectCentral(); +char query[512]; + +safef(query, sizeof(query), "select dbList from %s where id=%d", + hubStatusTableName, id); +char *dbList = sqlQuickString(conn, query); +boolean gotIt = FALSE; + +if (nameInCommaList(database, dbList)) + gotIt = TRUE; + +hDisconnectCentral(&conn); + +freeMem(dbList); + +return gotIt; +} + +static boolean fetchHub(char *database, char *url, boolean unlisted) +{ +struct errCatch *errCatch = errCatchNew(); +struct trackHub *tHub = NULL; +boolean gotWarning = FALSE; +unsigned id = 0; + +if (errCatchStart(errCatch)) + tHub = trackHubOpen(url, "1"); // open hub.. it'll get renamed later +errCatchEnd(errCatch); +if (errCatch->gotError) + { + gotWarning = TRUE; + warn(errCatch->message->string); + } +errCatchFree(&errCatch); + +if (gotWarning) + { + return 0; + } + +if (hashLookup(tHub->genomeHash, database) != NULL) + { + enterHubInStatus(tHub, unlisted); + } +else + { + warn("requested hub at %s does not have data for %s\n", url, database); + return 0; + } + +trackHubClose(&tHub); + +char *errorMessage = NULL; +id = getHubId(url, &errorMessage); +return id; +} + +static void getAndSetHubStatus(char *database, struct cart *cart, char *url, + boolean set, boolean unlisted) +{ +char *errorMessage = NULL; +unsigned id; + +if ((id = getHubId(url, &errorMessage)) == 0) + { + if ((id = fetchHub(database, url, unlisted)) == 0) + return; + } +else if (!hubHasDatabase(id, database)) + { + warn("requested hub at %s does not have data for %s\n", url, database); + return; + } + +char hubName[32]; +safef(hubName, sizeof(hubName), "%s%u", hgHubConnectHubVarPrefix, id); +if (set) + cartSetString(cart, hubName, "1"); +} + +unsigned hubFindOrAddUrlInStatusTable(char *database, struct cart *cart, + char *url, char **errorMessage) +/* find this url in the status table, and return its id and errorMessage (if an errorMessage exists) */ +{ +int id = 0; + +*errorMessage = NULL; + +if ((id = getHubId(url, errorMessage)) > 0) + return id; + +getAndSetHubStatus(database, cart, url, FALSE, FALSE); + +if ((id = getHubId(url, errorMessage)) == 0) + errAbort("inserted new hubUrl %s, but cannot find it", url); + +return id; +} + +void hubCheckForNew(char *database, struct cart *cart) +/* see if the user just typed in a new hub url */ +{ +char *url = cartOptionalString(cart, hgHubDataText); + +if (url != NULL) + { + getAndSetHubStatus(database, cart, url, TRUE, TRUE); + cartRemove(cart, hgHubDataText); + } +} + +void hubClearStatus(char *url) +{ +struct sqlConnection *conn = hConnectCentral(); +char query[512]; + +safef(query, sizeof(query), "select id from %s where hubUrl = \"%s\"", hubStatusTableName, url); +unsigned id = sqlQuickNum(conn, query); + +if (id == 0) + errAbort("could not find url %s in status table (%s)\n", + url, hubStatusTableName); + +safef(query, sizeof(query), "delete from %s where hubUrl = \"%s\"", hubStatusTableName, url); + +sqlUpdate(conn, query); +hDisconnectCentral(&conn); + +} +