ef2869665d8c2d4fe59743faabe050de406a5278 braney Wed Apr 13 18:00:32 2011 -0700 add support for private hubs. Needs more work and doc, the biggest problem I know of is that you can't switch off the private hubs, but it should give folks an idea of how I'm thinking of supporting them. diff --git src/hg/lib/hubConnect.c src/hg/lib/hubConnect.c index d7baeb5..4c9d923 100644 --- src/hg/lib/hubConnect.c +++ src/hg/lib/hubConnect.c @@ -88,103 +88,207 @@ slPairFreeList(&hubVarList); cartSetString(cart, hubConnectTrackHubsVarName, trackHubs->string); dyStringFree(&trackHubs); cartRemove(cart, hgHubConnectRemakeTrackHub); } } struct slName *hubConnectHubsInCart(struct cart *cart) /* Return list of track hub ids that are turned on. */ { hubConnectRemakeTrackHubVar(cart); char *trackHubString = cartOptionalString(cart, hubConnectTrackHubsVarName); return slNameListFromString(trackHubString, ' '); } -struct hubConnectStatus *hubConnectStatusForId(struct sqlConnection *conn, int id) +static struct hubConnectStatus *hubConnectStatusForIdDb(struct sqlConnection *conn, int id) /* Given a hub ID return associated status. Returns NULL if no such hub. If hub * exists but has problems will return with errorMessage field filled in. */ + /* If the id is negative, then the hub is private and the number is the + * offset into the private hubfile in the trash */ { struct hubConnectStatus *hub = NULL; char query[1024]; safef(query, sizeof(query), "select id,shortLabel,longLabel,hubUrl,errorMessage,dbCount,dbList from %s where id=%d", hubConnectTableName, id); struct sqlResult *sr = sqlGetResult(conn, query); char **row = sqlNextRow(sr); if (row != NULL) { AllocVar(hub); hub->id = sqlUnsigned(row[0]); hub->shortLabel = cloneString(row[1]); hub->longLabel = cloneString(row[2]); hub->hubUrl = cloneString(row[3]); hub->errorMessage = cloneString(row[4]); hub->dbCount = sqlUnsigned(row[5]); int sizeOne; sqlStringDynamicArray(row[6], &hub->dbArray, &sizeOne); assert(sizeOne == hub->dbCount); } sqlFreeResult(&sr); return hub; } +boolean hubWriteToFile(FILE *f, struct hubConnectStatus *el) +/* write out a hubConnectStatus structure to a file */ +{ +char sep = '\t'; +char lastSep = '\n'; + +fprintf(f, "%d", el->id); +fputc(sep,f); +fprintf(f, "%s", el->shortLabel); +fputc(sep,f); +fprintf(f, "%s", el->longLabel); +fputc(sep,f); +fprintf(f, "%s", el->hubUrl); +fputc(sep,f); +fprintf(f, "%s", el->errorMessage); +fputc(sep,f); +fprintf(f, "%u", el->dbCount); +fputc(sep,f); +int ii; +for(ii=0; ii < el->dbCount; ii++) + { + fprintf(f, "%s", el->dbArray[ii]); + if (ii != el->dbCount - 1) + fprintf(f, ","); + } +fputc(lastSep,f); + +return TRUE; +} + + +static struct hubConnectStatus *readHubFromFile(struct lineFile *lf) +{ +struct hubConnectStatus *hub = NULL; +char *row[5]; +int count; +if ((count = lineFileChopTab(lf, row)) != ArraySize(row)) + errAbort("expect %d fields on line %d in %s, got %d\n",(int)ArraySize(row),lf->lineIx, lf->fileName, count); + +AllocVar(hub); +hub->id = sqlSigned(row[0]); +hub->shortLabel = cloneString(row[1]); +hub->longLabel = cloneString(row[2]); +hub->hubUrl = cloneString(row[3]); +//hub->errorMessage = cloneString(row[4]); +hub->dbCount = sqlUnsigned(row[4]); +//int sizeOne; +//sqlStringDynamicArray(row[5], &hub->dbArray, &sizeOne); +//assert(sizeOne == hub->dbCount); + +return hub; +} + +#define HUBFILE_CART_NAME "hghub_file" + +char *hubFileVar() +/* return the name of the cart variable that holds the name of the + * file in trash that has private hubs */ +{ +return HUBFILE_CART_NAME; +} + +struct hubConnectStatus *hubConnectStatusForIdFile(struct cart *cart, int id) + /* id is offset into the private hubfile in the trash */ +{ +struct hubConnectStatus *hub = NULL; +char *fileVar = hubFileVar(); +char *hubFileName = cartOptionalString(cart, fileVar); +struct lineFile *lf = lineFileOpen(hubFileName, TRUE); +int lineSize; +char *line; +int count = id; + +while(--count) + if (lineFileNext(lf, &line, &lineSize) == FALSE) + errAbort("not enough lines in %s to find line number %d\n", + lf->fileName, id); + +hub = readHubFromFile(lf); + +return hub; +} + +struct hubConnectStatus *hubConnectStatusForId(struct cart *cart, struct sqlConnection *conn, int id) +/* Given a hub ID return associated status. Returns NULL if no such hub. If hub + * exists but has problems will return with errorMessage field filled in. */ + /* If the id is negative, then the hub is private and the number is the + * offset into the private hubfile in the trash */ +{ +struct hubConnectStatus *hub = NULL; + +if (id < 0) + hub = hubConnectStatusForIdFile(cart, -id); +else + hub = hubConnectStatusForIdDb(conn, id); + +return hub; +} + + struct hubConnectStatus *hubConnectStatusListFromCart(struct cart *cart) /* Return list of track hubs that are turned on by user in cart. */ { struct hubConnectStatus *hubList = NULL, *hub; struct slName *name, *nameList = hubConnectHubsInCart(cart); struct sqlConnection *conn = hConnectCentral(); for (name = nameList; name != NULL; name = name->next) { - int id = sqlUnsigned(name->name); - hub = hubConnectStatusForId(conn, id); + int id = sqlSigned(name->name); + hub = hubConnectStatusForId(cart, conn, id); 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; assert(isdigit(trackName[0])); return atoi(trackName); } 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; assert(isdigit(trackName[0])); trackName = strchr(trackName, '_'); assert(trackName != NULL); return trackName + 1; } -struct trackHub *trackHubFromId(int hubId) +struct trackHub *trackHubFromId(struct cart *cart, int hubId) /* Given a hub ID number, return corresponding trackHub structure. * ErrAbort if there's a problem. */ { struct sqlConnection *conn = hConnectCentral(); -struct hubConnectStatus *status = hubConnectStatusForId(conn, hubId); +struct hubConnectStatus *status = hubConnectStatusForId(cart, conn, hubId); hDisconnectCentral(&conn); if (status == NULL) errAbort("The hubId %d was not found", hubId); if (!isEmpty(status->errorMessage)) errAbort("Hub %s at %s has the error: %s", status->shortLabel, status->hubUrl, status->errorMessage); char hubName[16]; safef(hubName, sizeof(hubName), "hub_%d", hubId); struct trackHub *hub = trackHubOpen(status->hubUrl, hubName); hubConnectStatusFree(&status); return hub; } static struct trackDb *findSuperTrack(struct trackDb *tdbList, char *trackName) /* discover any supertracks, and if there are some add them @@ -198,39 +302,40 @@ { /* save away the next pointer becuase we may detach this node and * add it to its supertrack parent */ next = tdb->next; if (tdb->parent != NULL && sameString(trackName, tdb->parent->track)) { /* found a supertrack with the right name, add this child */ p = tdb->parent; slAddHead(&p->subtracks, tdb); } } return p; } -struct trackDb *hubConnectAddHubForTrackAndFindTdb(char *database, - char *trackName, struct trackDb **pTdbList, struct hash *trackHash) +struct trackDb *hubConnectAddHubForTrackAndFindTdb(struct cart *cart, + char *database, char *trackName, struct trackDb **pTdbList, + struct hash *trackHash) /* Go find hub for trackName (which will begin with hub_), and load the tracks * for it, appending to end of list and adding to trackHash. Return the * trackDb associated with trackName. This will also fill in the html fields, * but just for that track and it's parents. */ { int hubId = hubIdFromTrackName(trackName); -struct trackHub *hub = trackHubFromId(hubId); +struct trackHub *hub = trackHubFromId(cart, hubId); struct trackHubGenome *hubGenome = trackHubFindGenome(hub, database); struct trackDb *tdbList = trackHubTracksForGenome(hub, hubGenome); tdbList = trackDbLinkUpGenerations(tdbList); tdbList = trackDbPolishAfterLinkup(tdbList, database); rAddTrackListToHash(trackHash, tdbList, NULL, FALSE); if (pTdbList != NULL) *pTdbList = slCat(*pTdbList, tdbList); struct trackDb *tdb = hashFindVal(trackHash, trackName); if (tdb == NULL) // superTracks aren't in the hash... look in tdbList tdb = findSuperTrack(tdbList, trackName); if (tdb == NULL) errAbort("Can't find track %s in %s", trackName, hub->url);