08ec0b5265b884be1c7885ebe73db95515beca0d jcasper Fri Aug 16 11:27:45 2024 -0700 Basic support for multiple decorators, refs #32644 diff --git src/hg/hgTracks/hgTracks.c src/hg/hgTracks/hgTracks.c index 752f54a..6576258 100644 --- src/hg/hgTracks/hgTracks.c +++ src/hg/hgTracks/hgTracks.c @@ -7734,90 +7734,92 @@ int tdbHasDecorators(struct track *track) { struct slName *decoratorSettings = trackDbSettingsWildMatch(track->tdb, "decorator.*"); if (decoratorSettings) { slNameFreeList(&decoratorSettings); return 1; } return 0; } void loadDecorators(struct track *track) -/* Load decorations from a source (file) and put them in a decorator, then add that - * decorator to the list of the track's decorators. Within the new decorator, each +/* Load decorations from a source (file) and put them into decorators, then add those + * decorators to the list of the track's decorators. Within the new decorators, each * of the decorations should have been entered into a hash table that is indexed by the * name of the linked feature. That way when we're drawing the linked feature, we'll * be able to quickly locate the associated decorations. - * - * Note that this will need amendment when multiple decoration sources are possible. */ { -char *decoratorUrl = trackDbSetting(track->tdb, "decorator.default.bigDataUrl"); +struct trackDb *decoratorTdbs = getTdbsForDecorators(track->tdb); +for (struct trackDb *decoratorTdb = decoratorTdbs; decoratorTdb != NULL; + decoratorTdb = decoratorTdb->next) + { + char *decoratorUrl = trackDbSetting(decoratorTdb, "bigDataUrl"); if (!decoratorUrl) { - errAbort ("Decorator tags are present in track %s, but no decorator file specified (decorator.default.bigDataUrl is missing)", - track->track); - return; + warn ("Decorator tags are present as %s, but no decorator file specified (bigDataUrl is missing)", + decoratorTdb->track); + continue; } struct bbiFile *bbi = NULL; struct errCatch *errCatch = errCatchNew(); if (errCatchStart(errCatch)) { if (isValidBigDataUrl(decoratorUrl,TRUE)) bbi = bigBedFileOpenAlias(decoratorUrl, chromAliasFindAliases); } errCatchEnd(errCatch); if (errCatch->gotError) { - errAbort ("Network error while attempting to retrieve decorations from %s (track %s) - %s", + warn ("Network error while attempting to retrieve decorations from %s (track %s) - %s", decoratorUrl, track->track, dyStringContents(errCatch->message)); - return; + continue; } errCatchFree(&errCatch); struct asObject *decoratorFileAsObj = asParseText(bigBedAutoSqlText(bbi)); if (!asColumnNamesMatchFirstN(decoratorFileAsObj, decorationAsObj(), DECORATION_NUM_COLS)) { - errAbort ("Decoration file associated with track %s (%s) does not match the expected format - see decoration.as", + warn ("Decoration file associated with track %s (%s) does not match the expected format - see decoration.as", track->track, decoratorUrl); - return; + continue; } -struct trackDb *decoratorTdb = getTdbForDecorator(track->tdb); struct bigBedFilter *filters = bigBedBuildFilters(cart, bbi, decoratorTdb); struct lm *lm = lmInit(0); struct bigBedInterval *result = bigBedIntervalQuery(bbi, chromName, winStart, winEnd, 0, lm); struct mouseOverScheme *mouseScheme = mouseOverSetupForBbi(decoratorTdb, bbi); // insert resulting entries into track->decorators, leaving room for having multiple sources applied // to the same track in the future. if (track->decoratorGroup == NULL) track->decoratorGroup = newDecoratorGroup(); struct decorator* newDecorators = decoratorListFromBbi(decoratorTdb, chromName, result, filters, bbi, mouseScheme); track->decoratorGroup->decorators = slCat(track->decoratorGroup->decorators, newDecorators); for (struct decorator *d = track->decoratorGroup->decorators; d != NULL; d = d->next) d->group = track->decoratorGroup; lmCleanup(&lm); bigBedFileClose(&bbi); } +} static void *remoteParallelLoad(void *threadParam) /* Each thread loads tracks in parallel until all work is done. */ { pthread_t *pthread = threadParam; struct paraFetchData *pfd = NULL; pthread_detach(*pthread); // this thread will never join back with it's progenitor // Canceled threads that might leave locks behind, // so the theads are detached and will be neither joined nor canceled. boolean allDone = FALSE; while(1) { pthread_mutex_lock( &pfdMutex ); if (!pfdList) {