36d5542588a99a3e44bf65d16aa3c4600b562b87
braney
  Tue Jun 8 10:10:30 2021 -0700
changes in response to code review #27643

diff --git src/hg/lib/hdb.c src/hg/lib/hdb.c
index 76d4538..09be762 100644
--- src/hg/lib/hdb.c
+++ src/hg/lib/hdb.c
@@ -47,38 +47,30 @@
 #include "regexHelper.h"
 #include "filePath.h"
 #include "wikiLink.h"
 #include "cheapcgi.h"
 #include "chromAlias.h"
 
 
 #ifdef LOWELAB
 #define DEFAULT_PROTEINS "proteins060115"
 #define DEFAULT_GENOME "Pyrobaculum aerophilum"
 #else
 #define DEFAULT_PROTEINS "proteins"
 #define DEFAULT_GENOME "Human"
 #endif
 
-static unsigned trackDbCartVersion = 0;
-
-unsigned hdbGetTrackCartVersion()
-/* Get the cart version that our current trackDb wants to use. */
-{
-return trackDbCartVersion;
-}
-
 static struct sqlConnCache *hdbCc = NULL;  /* cache for primary database connection */
 static struct sqlConnCache *centralCc = NULL;
 static char *centralDb = NULL;
 static struct sqlConnCache *cartCc = NULL;  /* cache for cart; normally same as centralCc */
 static char *cartDb = NULL;
 static char *hdbTrackDb = NULL;
 
 /* cached list of tables in databases.  This keeps a hash of databases to
  * hashes of track/table name to slName list of actual table names, which
  * might be split.  Since individual tables can be mapped to different
  * profiles, and this information is only available when processing trackDb,
  * another table is kept to determine if these need to be checked.
  */
 static struct hash *tableList = NULL; // db to track to tables
 static struct hash *tableListProfChecked = NULL;  // profile:db that have been check
@@ -4194,31 +4186,31 @@
     }
 }
 
 struct trackDb *trackDbPolishAfterLinkup(struct trackDb *tdbList, char *db)
 /* Do various massaging that can only be done after parent/child
  * relationships are established. */
 {
 tdbList = pruneEmpties(tdbList, db, hIsPrivateHost() || hIsPreviewHost(), 0);
 addChildRefsToParents(tdbList);
 trackDbContainerMarkup(NULL, tdbList);
 rInheritFields(tdbList);
 slSort(&tdbList, trackDbCmp);
 return tdbList;
 }
 
-struct trackDb *hTrackDb(char *db)
+struct trackDb *hTrackDbWithCartVersion(char *db, int *retCartVersion)
 /* Load tracks associated with current db.
  * Supertracks are loaded as a trackDb, but are not in the returned list,
  * but are accessible via the parent pointers of the member tracks.  Also,
  * the supertrack trackDb subtrack fields are not set here (would be
  * incompatible with the returned list)
  * Returns list sorted by priority
  *	NOTE: this result is cached, do not free it !
  */
 {
 if (trackHubDatabase(db))
     return NULL;
 struct trackDb *tdbList = NULL;
 
 boolean doCache = trackDbCacheOn();
 char *tdbPathString = hTrackDbPath();
@@ -4238,50 +4230,67 @@
     hFreeConn(&conn);
 
     long now = clock1();
 
     // if the trackDb table has changed in the last five minutes, avoid caching because the table may
     // not be done changing.  Updates are not atomic.
     if (now - newestTime < 5 * 60)
         doCache = 0;
     else
         {
         struct trackDb *cacheTdb = trackDbCache(db, tdbPathString, newestTime);
 
         if (cacheTdb != NULL)
             {
             if (sameString(cacheTdb->track, "cartVersion"))
-                trackDbCartVersion = -cacheTdb->priority;
-            return cacheTdb->next;
+                {
+                // Convert negative cartVersion (for priority-ordering) back to positive cartVersion
+                if (retCartVersion)
+                    *retCartVersion = -cacheTdb->priority;
+                cacheTdb = cacheTdb->next;
+                }
+            return cacheTdb;
             }
 
         memCheckPoint(); // we want to know how much memory is used to build the tdbList
         }
     }
 
 tdbList = loadTrackDb(db, NULL);
 tdbList = trackDbLinkUpGenerations(tdbList);
 tdbList = trackDbPolishAfterLinkup(tdbList, db);
 
 if (doCache)
     trackDbCloneTdbListToSharedMem(db, tdbPathString, tdbList, memCheckPoint());
 
+// Store negative cartVersion in priority field so that cartVersion "track" is first in tdbList
 if (sameString(tdbList->track, "cartVersion"))
-    trackDbCartVersion = -tdbList->priority;
+    {
+    if (retCartVersion)
+        *retCartVersion = -tdbList->priority;
+    tdbList = tdbList->next;
+    }
+
 return tdbList->next;
 }
 
+struct trackDb *hTrackDb(char *db)
+/* see hTrackDbWithCartVersion above. */
+{
+return hTrackDbWithCartVersion(db, NULL);
+}
+
 static struct trackDb *loadAndLookupTrackDb(struct sqlConnection *conn,
 					    char *where)
 /* Load trackDb object(s). Nothing done for composite tracks here. */
 {
 return loadTrackDb(sqlGetDatabase(conn), where);
 }
 
 static struct trackDb *loadTrackDbForTrack(struct sqlConnection *conn,
 					   char *track)
 /* Load trackDb object for a track. this is common code for two external
  * functions. Handle composite tracks and subtrack inheritance here.
  */
 {
 struct trackDb *trackTdb = NULL;
 char where[256];