d1bc57639309864bb2665bd46eddfe75863f76e4 braney Tue Apr 23 16:42:54 2024 -0700 rearrange how we're doing hub groups. diff --git src/hg/lib/hubConnect.c src/hg/lib/hubConnect.c index 4fee1b1..2be2a6a 100644 --- src/hg/lib/hubConnect.c +++ src/hg/lib/hubConnect.c @@ -16,30 +16,45 @@ #include "hdb.h" #include "net.h" #include "trackHub.h" #include "hubConnect.h" #include "hui.h" #include "errCatch.h" #include "obscure.h" #include "hgConfig.h" #include "grp.h" #include "udc.h" #include "hubPublic.h" #include "genark.h" #include "asmAlias.h" #include "cheapcgi.h" +boolean hubsCanAddGroups() +/* can track hubs have their own groups? */ +{ +static boolean canHubs = FALSE; +static boolean canHubsSet = FALSE; + +if (!canHubsSet) + { + canHubs = cfgOptionBooleanDefault("trackHubsCanAddGroups", FALSE); + canHubsSet = TRUE; + } + +return canHubs; +} + boolean isHubTrack(char *trackName) /* Return TRUE if it's a hub track. */ { return startsWith(hubTrackPrefix, trackName); } static char *hubStatusTableName = NULL; static char *_hubPublicTableName = NULL; static char *getHubStatusTableName() /* return the hubStatus table name from the environment, * or hg.conf, or use the default. Cache the result */ { if (hubStatusTableName == NULL) hubStatusTableName = cfgOptionEnvDefault("HGDB_HUB_STATUS_TABLE", @@ -347,30 +362,45 @@ slReverse(&hubList); return hubList; } int hubIdFromCartName(char *cartName) /* Given something like "hgHubConnect.hub.123" return 123 */ { assert(startsWith("hgHubConnect.hub.", cartName)); char *ptr1 = strchr(cartName, '.'); char *ptr2 = strchr(ptr1 + 1, '.'); return sqlUnsigned(ptr2+1); } +char *hubNameFromGroupName(char *groupName) +/* Given something like "hub_123_myWig" return hub_123 */ +{ +char *hubName = cloneString(groupName); + +char *ptr1 = hubName; +ptr1 += 4; +char *ptr2 = strchr(ptr1, '_'); + +if (ptr2 != NULL) + *ptr2 = 0; + +return hubName; +} + unsigned hubIdFromTrackName(char *trackName) /* Given something like "hub_123_myWig" return 123 */ { assert(startsWith("hub_", 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; @@ -866,49 +896,74 @@ else if (tHub != NULL) { int dbCount = 0; char *dbList = getDbList(tHub, &dbCount); // users may include quotes in their hub names requiring escaping sqlSafef(query, sizeof(query), "update %s set shortLabel=\"%s\",longLabel=\"%s\",dbCount=\"%d\",dbList=\"%s\",errorMessage=\"\",lastOkTime=now() where id=%d", getHubStatusTableName(), tHub->shortLabel, tHub->longLabel, dbCount, dbList, hub->id); sqlUpdate(conn, query); } hDisconnectCentral(&conn); } -struct trackDb *hubAddTracks(struct hubConnectStatus *hub, char *database, boolean *foundFirstGenome, struct hash *trackDbNameHash) +static void grpListAddHubName(struct grp *grpList, struct trackHub *hub) +/* Add the hub name to the groups defined by a hub. */ +{ +char buffer[4096]; + +for (; grpList; grpList = grpList->next) + { + safef(buffer, sizeof buffer, "%s_%s", hub->name, grpList->name); + grpList->name = cloneString(buffer); + safef(buffer, sizeof buffer, "Hub: %s : %s", hub->shortLabel, grpList->label); + grpList->label = cloneString(buffer); + } +} + +struct trackDb *hubAddTracks(struct hubConnectStatus *hub, char *database, boolean *foundFirstGenome, struct hash *trackDbNameHash, struct grp **hubGroups) /* Load up stuff from data hub and append to list. The hubUrl points to * a trackDb.ra format file. Only the first example of a genome gets to * populate groups, the others get a group for the trackHub. A particular * trackDb is only read once even if referenced from more than one hub. */ { struct trackDb *tdbList = NULL; struct trackHub *trackHub = hub->trackHub; if (trackHub != NULL) { struct trackHubGenome *hubGenome = trackHubFindGenome(trackHub, database); if ((hubGenome == NULL) || hashLookup(trackDbNameHash, hubGenome->trackDbFile)) hubGenome = NULL; // we already saw this trackDb, so ignore this stanza else hashStore(trackDbNameHash, hubGenome->trackDbFile); if (hubGenome != NULL) { + // add groups + if ((hubGenome->groups != NULL) && hubsCanAddGroups()) + { + struct grp *list = readGroupRa(hubGenome->groups); + grpListAddHubName(list, hub->trackHub); + + if (hubGroups) + *hubGroups = slCat(*hubGroups, list); + } + + // now grab tracks boolean doCache = trackDbCacheOn(); if (doCache) { // we have to open the trackDb file to get the udc cache to check for an update struct udcFile *checkCache = udcFileMayOpen(hubGenome->trackDbFile, NULL); if (checkCache != NULL) { time_t time = udcUpdateTime(checkCache); udcFileClose(&checkCache); struct trackDb *cacheTdb = trackDbHubCache(hubGenome->trackDbFile, time); if (cacheTdb && hubGenome->quickLiftChain) cacheTdb = fixForQuickLift(cacheTdb, hubGenome, hub); @@ -933,62 +988,64 @@ if (tdbList && hubGenome->quickLiftChain) tdbList = fixForQuickLift(tdbList, hubGenome, hub); } } return tdbList; } static struct grp *grpFromHub(struct hubConnectStatus *hub) /* Make up a grp structur from hub */ { struct grp *grp; AllocVar(grp); char name[16]; safef(name, sizeof(name), "hub_%d", hub->id); grp->name = cloneString(name); -grp->label = cloneString(hub->shortLabel); +char buffer[4096]; +safef(buffer, sizeof buffer, "Hub: %s", hub->shortLabel); +grp->label = cloneString(buffer); return grp; } struct trackDb *hubCollectTracks( char *database, struct grp **pGroupList) /* Generate trackDb structures for all the tracks in attached hubs. * Make grp structures for each hub. Returned group list is reversed. */ { // return the cached copy if it exists static struct trackDb *hubTrackDbs; static struct grp *hubGroups; if (hubTrackDbs != NULL) { if (pGroupList != NULL) *pGroupList = hubGroups; return hubTrackDbs; } struct hubConnectStatus *hub, *hubList = hubConnectGetHubs(); struct trackDb *tdbList = NULL; boolean foundFirstGenome = FALSE; struct hash *trackDbNameHash = newHash(5); for (hub = hubList; hub != NULL; hub = hub->next) { if (isEmpty(hub->errorMessage)) { /* error catching in so it won't just abort */ struct errCatch *errCatch = errCatchNew(); if (errCatchStart(errCatch)) { - struct trackDb *thisList = hubAddTracks(hub, database, &foundFirstGenome, trackDbNameHash); + struct trackDb *thisList = hubAddTracks(hub, database, &foundFirstGenome, trackDbNameHash, &hubGroups); tdbList = slCat(tdbList, thisList); } errCatchEnd(errCatch); if (errCatch->gotError) { warn("%s", errCatch->message->string); hubUpdateStatus( errCatch->message->string, hub); } else { struct grp *grp = grpFromHub(hub); slAddHead(&hubGroups, grp); hubUpdateStatus(NULL, hub); }