eb7e6ccb9b23c2dd5cd82de0237c6f25aecd2da1 max Thu Sep 17 06:02:11 2026 -0700 Hub tracks must not claim an undecorated name that a native track owns #Preview2 week - bugs introduced now will need a build patch to fix A hub track can be named on a URL, or found in the cart, without its "hub__" prefix, so that hub links stay readable. Nothing checked whether the assembly already had a track of that name, so when it did, the hub track took the variable: with the MethBase2 hub attached, setting the native hg38 Methbase track's visibility moved it to hub__Methbase and dropped it from the native track, which then did not draw. The two share the name "Methbase", and their subtracks share names too, so the same went for the _sel checkboxes. hubTrackOwnsBareName() now gates the seven places that fall back to the bare name - track and subtrack visibility, supertrack visibility, the two _hideKids variables, and the _sel checkbox. The bare name is the hub track's only where the assembly has no track of that name; otherwise it belongs to the native one, whose own pass over the track list consumes it. It answers from the track list loadFromTrackDb() has already built, so it costs a hash lookup: hub tracks are always prefixed in that list, so an undecorated name can only match a native track. A caller with no list to register (hgTrackUi) falls back to a single-row trackDb query per distinct bare name, cached. With 500 hub subtracks visible and 500 bare names on the URL - far past anything real - that is 189 queries either way, against 1189 for a query per name. Also clarifies the comments on hTrackDbWithCartVersion() and tdbForTrack(): the "this result is cached" note means the shared-memory trackDb cache only, which is off unless cacheTrackDbDir is set, and there is no memoizing besides it - so hTrackDbForTrack() per name reloads the whole trackDb each call. Measured at 57 seconds for 500 names before I abandoned that approach. refs #34246 diff --git src/hg/inc/hui.h src/hg/inc/hui.h index 1bd86df1e1b..a8db1b5e22f 100644 --- src/hg/inc/hui.h +++ src/hg/inc/hui.h @@ -1137,30 +1137,46 @@ * Generally true. Exceptions are specially defined subgroups */ int multViewCount(struct trackDb *parentTdb); /* returns the number of multiView views declared */ int tvConvertToNumericOrder(enum trackVisibility v); /* Convert the enum to numeric order of display power full=4,hide=0 */ int tvCompare(enum trackVisibility a, enum trackVisibility b); /* enum trackVis isn't in numeric order by visibility, so compare * symbolically: */ enum trackVisibility tvMin(enum trackVisibility a, enum trackVisibility b); /* Return the less visible of a and b. */ +void hubTrackBareNamesFromTdbList(struct trackDb *tdbList); +/* Let hubTrackOwnsBareName() answer from this list of tracks rather than from trackDb. + * A CGI that has already built the full track list should call this once, with it: the + * list holds the assembly's tracks and the attached hubs' together, and a hub track is + * always "hub__"-prefixed there, so an undecorated name can only match a native + * track. Without this the question costs a trackDb query per distinct bare name. */ + +boolean hubTrackOwnsBareName(char *db, char *hubTrack); +/* A hub track can be named on a URL or in the cart without its "hub__" prefix, so + * that hub links stay readable, and the visibility and selection code falls back to that + * bare name when the decorated one has no value. The bare name is the hub track's alone + * only when the assembly has no track of that name: when it does, the variable belongs to + * the native track, and letting the hub track take it moves the user's setting to a track + * they were not looking at and drops it from the one they were. Takes the decorated hub + * track name; FALSE for anything that isn't one. */ + enum trackVisibility tdbLocalVisibility(struct cart *cart, struct trackDb *tdb, boolean *subtrackOverride); // returns visibility NOT limited by ancestry. // Fills optional boolean if subtrack specific vis is found // If not NULL cart will be examined without ClosestToHome. // Folders/supertracks resolve to hide/full enum trackVisibility tdbVisLimitedByAncestors(struct cart *cart, struct trackDb *tdb, boolean checkBoxToo, boolean foldersToo); // returns visibility limited by ancestry. // This includes subtrack vis override and parents limit maximum. // cart may be null, in which case, only trackDb settings (default state) are examined // checkBoxToo means ensure subtrack checkbox state is visible // foldersToo means limit by folders (aka superTracks) as well. #define tdbVisLimitedByAncestry(cart,tdb,noFolders) \