fa7a11afb5f19dd5a2fa3382fc38662f34b6f147
braney
  Wed May 29 13:55:44 2019 -0700
first cut at caching trackDb in a shared memory location.   No changes
in running code if "cacheTrackDb" hg.conf variable doesn't exist

diff --git src/hg/lib/hdb.c src/hg/lib/hdb.c
index 6b3a27b..806341b 100644
--- src/hg/lib/hdb.c
+++ src/hg/lib/hdb.c
@@ -4092,55 +4092,66 @@
 rInheritFields(tdbList);
 slSort(&tdbList, trackDbCmp);
 return tdbList;
 }
 
 struct trackDb *hTrackDb(char *db)
 /* 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 !
  */
 {
-// FIXME: This is NOT CACHED and should be!  Since some callers (e.g. hgTables) consume the list,
-// I would suggest:
-// 1) static hash by db/hub
-// 2) call creates list if not in hash
-// 3) static (to this file) routine gives the actual tdb list
-// 4) public lib routine that returns fully cloned list
-// 5) public lib routine that returns cloned individual tdb complete with up/down inheritance
-// UNFORTUNATELY, cloning the memory with prove costly in time as well, because of all the pointers
-// to relink.  THEREFORE what should be done is to make the tdb list with const ->next pointers and
-// force discpline on the callers.  Sorts should be by hdb.c routines and any new lists (such as
-// hgTables makes) should be via tdbRefs.
-// SO we are back to being STALLED because of the volume of work.
-
-// static char *existingDb = NULL;
-// static struct trackDb *tdbList = NULL;
 struct trackDb *tdbList = NULL;
-//if (differentStringNullOk(existingDb, db))
-//    {
+
+boolean doCache = FALSE;
+if (sameOk(cfgOption("cacheTrackDb"), "on"))
+    doCache = TRUE;
+
+if (doCache)
+    {
+    // look for this db in the cache, if it's found it will have a file name, an address, and a size
+    boolean foundDb = FALSE;
+
+    if (foundDb)
+        {
+        unsigned long size = 24402580;
+        char *file = "brtest/flart";
+        unsigned long address = 0x7000000;
+        struct trackDb *clone = mapSharedMemTrackDb(file, address, size);
+        if (clone != NULL)
+            return clone;
+        }
+    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);
-//    freeMem(existingDb);
-//    existingDb = cloneString(db);
-//    }
+
+if (doCache)
+    {
+    struct trackDb *clone = cloneTdbListToSharedMem(tdbList, memCheckPoint());
+
+    // record clone in registy
+    if (clone == NULL)
+        warn("unable to clone trackDb");
+    }
+
 return tdbList;
 }
 
 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.
  */