f1464a78ed45c0f2c2c47112d5ec0585e875208e
braney
  Tue Oct 30 15:01:29 2018 -0700
some optimizations to speed up trackDb loads on huge hubs

diff --git src/hg/lib/trackDbCustom.c src/hg/lib/trackDbCustom.c
index a5623b9..a6d2919 100644
--- src/hg/lib/trackDbCustom.c
+++ src/hg/lib/trackDbCustom.c
@@ -110,31 +110,46 @@
 
 static void trackDbAddRelease(struct trackDb *bt, char *releaseTag)
 /* Add release tag */
 {
 hashAdd(bt->settingsHash, "release", cloneString(releaseTag));
 }
 
 static void trackDbAddInfo(struct trackDb *bt,
         char *var, char *value, struct lineFile *lf)
 /* Add info from a variable/value pair to browser table. */
 {
 if (sameString(var, "track"))
     parseTrackLine(bt, value, lf);
 if (bt->settingsHash == NULL)
     bt->settingsHash = hashNew(7);
-hashAdd(bt->settingsHash, var, cloneString(value));
+if (bt->viewHash == NULL)
+    bt->viewHash = hashNew(7);
+char *storeValue = cloneString(value);
+
+// squirrel away views
+if (startsWith("subGroup", var))
+    {
+    char *ptr = strchr(value, ' ');
+    if (ptr)
+        *ptr = 0;
+    hashAdd(bt->viewHash, value, storeValue);
+    if (ptr)
+        *ptr = ' ';
+    }
+
+hashAdd(bt->settingsHash, var, storeValue);
 
 if (bt->overrides != NULL)
     hashAdd(bt->overrides, var, NULL);
 }
 
 //not needed?
 int bedDetailSizeFromType(char *type)
 /* parse bedSize from type line for bedDetail, assume 4 if none */
 {
 int ret = 4;  /* minimal expected */
 char *words[3];
 int wordCount = chopLine(cloneString(type), words);
 if (wordCount > 1)
     ret = atoi(words[1]) - 2; /* trackDb has field count, we want bedSize */
 return ret;
@@ -420,30 +435,40 @@
         break;
     lineEnd = strchr(s, '\n');
     if (lineEnd != NULL)
         *lineEnd++ = 0;
     key = nextWord(&s);
     val = skipLeadingSpaces(s);
     trackDbUpdateOldTag(&key, &val);
     s = lineEnd;
     val = lmCloneString(hash->lm, val);
     hashAdd(hash, key, val);
     }
 freeMem(dupe);
 return hash;
 }
 
+char *trackDbViewSetting(struct trackDb *tdb, char *name)
+/* Return view setting from tdb, but *not* any of it's parents. */
+{
+if (tdb == NULL)
+    errAbort("Program error: null tdb passed to trackDbSetting.");
+if (tdb->viewHash == NULL)
+    return NULL;
+return hashFindVal(tdb->viewHash, name);
+}
+
 char *trackDbLocalSetting(struct trackDb *tdb, char *name)
 /* Return setting from tdb, but *not* any of it's parents. */
 {
 if (tdb == NULL)
     errAbort("Program error: null tdb passed to trackDbSetting.");
 if (tdb->settingsHash == NULL)
     tdb->settingsHash = trackDbSettingsFromString(tdb->settings);
 return hashFindVal(tdb->settingsHash, name);
 }
 
 struct slName *trackDbLocalSettingsWildMatch(struct trackDb *tdb, char *expression)
 // Return local settings that match expression else NULL.  In alpha order.
 {
 if (tdb == NULL)
     errAbort("Program error: null tdb passed to trackDbSetting.");
@@ -1277,30 +1302,47 @@
 struct _membersForAll *tdbExtrasMembersForAll(struct trackDb *tdb)
 // Returns composite view/dimension members for all, else NULL.
 {
 struct tdbExtras *extras = tdb->tdbExtras;
 if (extras)
     return extras->membersForAll;
 return NULL;
 }
 
 void tdbExtrasMembersForAllSet(struct trackDb *tdb, struct _membersForAll *membersForAll)
 // Sets the composite view/dimensions members for all for later retrieval.
 {
 tdbExtrasGet(tdb)->membersForAll = membersForAll;
 }
 
+members_t *tdbExtrasMembers(struct trackDb *tdb, char *groupNameOrTag)
+// Returns subtrack members if already known, else NULL
+{
+struct tdbExtras *extras = tdbExtrasGet(tdb);
+
+if (extras->membersHash == NULL)
+    extras->membersHash = newHash(5);
+
+return (members_t *)hashFindVal(extras->membersHash, groupNameOrTag);
+}
+
+void tdbExtrasMembersSet(struct trackDb *tdb,  char *groupNameOrTag,  members_t *members)
+// Sets the subtrack members for later retrieval.
+{
+hashAdd(tdbExtrasGet(tdb)->membersHash, groupNameOrTag, members);
+}
+
 struct _membership *tdbExtrasMembership(struct trackDb *tdb)
 // Returns subtrack membership if already known, else NULL
 {
 struct tdbExtras *extras = tdb->tdbExtras;
 if (extras)
     return extras->membership;
 return tdbExtrasGet(tdb)->membership;
 }
 
 void tdbExtrasMembershipSet(struct trackDb *tdb,struct _membership *membership)
 // Sets the subtrack membership for later retrieval.
 {
 tdbExtrasGet(tdb)->membership = membership;
 }