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/hui.c src/hg/lib/hui.c
index 1a184ea..b90bb71 100644
--- src/hg/lib/hui.c
+++ src/hg/lib/hui.c
@@ -2550,137 +2550,111 @@
 
 static void dimensionsFree(dimensions_t **dimensions)
 // frees any previously obtained dividers setting
 {
 if (dimensions && *dimensions)
     {
     freeMem((*dimensions)->setting);
     freeMem((*dimensions)->names);
     freeMem((*dimensions)->subgroups);
     freez(dimensions);
     }
 }
 
 #define SUBGROUP_MAX 9
 
-enum filterCompositeType
-// Filter composites are drop-down checkbix-lists for selecting subtracks (eg hg19::HAIB TFBS)
-    {
-    fctNone=0,      // do not offer filter for this dimension
-    fctOne=1,       // filter composite by one or all
-    fctOneOnly=2,   // filter composite by only one
-    fctMulti=3,     // filter composite by multiselect: all, one or many
-    };
-
-typedef struct _members
-    {
-    int count;
-    char * groupTag;
-    char * groupTitle;
-    char **tags;
-    char **titles;
-    boolean *selected;
-    char * setting;
-    int *subtrackCount;              // count of subtracks
-    int *currentlyVisible;           // count of visible subtracks
-    struct slRef **subtrackList;     // set of subtracks belonging to each subgroup member
-    enum filterCompositeType fcType; // fctNone,fctOne,fctMulti
-    } members_t;
-
 int subgroupCount(struct trackDb *parentTdb)
 // How many subGroup setting does this parent have?
 {
 int ix;
 int count = 0;
 for (ix=1;ix<=SUBGROUP_MAX;ix++)
     {
     char subGrp[16];
     safef(subGrp, ArraySize(subGrp), "subGroup%d",ix);
     if (trackDbSetting(parentTdb, subGrp) != NULL)
 	count++;
     }
 return count;
 }
 
 char * subgroupSettingByTagOrName(struct trackDb *parentTdb, char *groupNameOrTag)
 // look for a subGroup by name (ie subGroup1) or tag (ie view) and return an unallocated char*
 {
 struct trackDb *ancestor;
 for (ancestor = parentTdb; ancestor != NULL; ancestor = ancestor->parent)
     {
-int ix;
     char *setting = NULL;
     if (startsWith("subGroup",groupNameOrTag))
         {
         setting = trackDbSetting(ancestor, groupNameOrTag);
         if (setting != NULL)
             return setting;
         }
-for (ix=1;ix<=SUBGROUP_MAX;ix++)
-    {
-    char subGrp[16];
-    safef(subGrp, ArraySize(subGrp), "subGroup%d",ix);
-    setting = trackDbSetting(ancestor, subGrp);
-    if (setting != NULL)  // Doesn't require consecutive subgroups
-	{
-	if (startsWithWord(groupNameOrTag,setting))
+    // these views are cached at trackDb read time
+    setting = trackDbViewSetting(ancestor, groupNameOrTag);
+    if (setting != NULL)
         return setting;
     }
-    }
-}
 return NULL;
 }
 
 boolean subgroupingExists(struct trackDb *parentTdb, char *groupNameOrTag)
 // Does this parent track contain a particular subgrouping?
 {
 return (subgroupSettingByTagOrName(parentTdb,groupNameOrTag) != NULL);
 }
 
 static members_t *subgroupMembersGet(struct trackDb *parentTdb, char *groupNameOrTag)
 // Parse a subGroup setting line into tag,title, names(optional) and values(optional),
 // returning the count of members or 0
 {
+members_t *members  = tdbExtrasMembers(parentTdb, groupNameOrTag);
+if (members != NULL)
+    return members;
+
 int ix,count;
 char *setting = subgroupSettingByTagOrName(parentTdb, groupNameOrTag);
 if (setting == NULL)
     return NULL;
-members_t *members = needMem(sizeof(members_t));
+members = needMem(sizeof(members_t));
 members->setting = cloneString(setting);
 char *words[SMALLBUF];
 count = chopLine(members->setting, words);
 assert(count <= ArraySize(words));
 if (count <= 1)
     {
     freeMem(members->setting);
     freeMem(members);
     return NULL;
     }
 members->groupTag   = words[0];
 members->groupTitle = strSwapChar(words[1],'_',' '); // Titles replace '_' with space
 members->tags       = needMem(count*sizeof(char*));
 members->titles     = needMem(count*sizeof(char*));
 for (ix = 2,members->count=0; ix < count; ix++)
     {
     char *name,*value;
     if (parseAssignment(words[ix], &name, &value))
 	{
 	members->tags[members->count]  = tagEncode(name);
 	members->titles[members->count] = strSwapChar(value,'_',' ');
 	members->count++;
 	}
     }
+tdbExtrasMembersSet(parentTdb, groupNameOrTag, members);
+
 return members;
 }
 
 static int membersSubGroupIx(members_t* members, char *tag)
 // Returns the index of the subgroup within the members struct (or -1)
 {
 int ix = 0;
 for (ix=0;ix<members->count;ix++)
     {
     if (members->tags[ix] != NULL && sameString(members->tags[ix],tag))
 	return ix;
     }
 return -1;
 }
 
@@ -2751,31 +2725,31 @@
 	{
 	members->tags[ixIn]             = NULL;
 	members->titles[ixIn]           = NULL;
 	members->subtrackCount[ixIn]    = 0;
 	members->currentlyVisible[ixIn] = 0;
 	//slFreeList(&members->subtrackList[ixIn]);  // No freeing at this moment
 	members->subtrackList[ixIn]     = NULL;
 	if (members->selected != NULL)
 	    members->selected[ixIn]     = FALSE;
 	}
     }
 members->count = ixOut;
 
 if (members->count == 0) // No members of this subgroup had a subtrack
     {
-    subgroupMembersFree(&members);
+    //subgroupMembersFree(&members);   // don't bother freeing
     return NULL;
     }
 
 return members;
 }
 
 enum
     {
     dimV=0, // View first
     dimX=1, // X & Y next
     dimY=2,
     dimA=3, // dimA is start of first of the optional non-matrix, non-view dimensions
     };
 
 typedef struct _membersForAll
@@ -3033,30 +3007,32 @@
 { // Uses membersForAll which may be in tdbExtraCache.  Do not free
 membersForAll_t* membersForAll = membersForAllSubGroupsGet(parentTdb,NULL);
 if (membersForAll == NULL)
     return NULL;
 
 int ix = membersForAllFindSubGroupIx(membersForAll,tag);
 if (ix >= 0)
     return membersForAll->members[ix];
 return NULL;
 }
 
 static void membersForAllSubGroupsFree(struct trackDb *parentTdb,
 				   membersForAll_t** membersForAllPtr)
 // frees memory for membersForAllSubGroups struct
 {
+return;    // don't bother freeing things, just takes time for no benefit
+
 if (membersForAllPtr && *membersForAllPtr)
     {
     if (parentTdb != NULL)
 	{
 	if (*membersForAllPtr == tdbExtrasMembersForAll(parentTdb))
 	    return;  // Don't free something saved to the tdbExtras!
 	}
     membersForAll_t* membersForAll = *membersForAllPtr;
     subgroupMembersFree(&(membersForAll->members[dimX]));
     subgroupMembersFree(&(membersForAll->members[dimY]));
     subgroupMembersFree(&(membersForAll->members[dimV]));
     int ix;
     for (ix=dimA;ix<membersForAll->dimMax;ix++)
 	{
 	//ASSERT(membersForAll->members[ix] != NULL);
@@ -3126,31 +3102,31 @@
     char *name,*value;
     if (parseAssignment(words[ix], &name, &value))
 	{
 	membership->subgroups[membership->count]  = name;
 	membership->membership[membership->count] = tagEncode(value);
 						    // tags will be used as classes by js
 	members_t* members = subgroupMembersGet(childTdb->parent, name);
 	membership->titles[membership->count] = NULL; // default
 	if (members != NULL)
 	    {
 	    int ix2 = stringArrayIx(membership->membership[membership->count],members->tags,
 				    members->count);
 	    if (ix2 != -1)
 		membership->titles[membership->count] =
 					strSwapChar(cloneString(members->titles[ix2]),'_',' ');
-	    subgroupMembersFree(&members);
+//	    subgroupMembersFree(&members);   /// don't bother freeing
 	    }
 	membership->count++;
 	}
     }
 tdbExtrasMembershipSet(childTdb,membership);
 return membership;
 }
 
 
 static boolean membershipInAllCurrentABCs(membership_t *membership,membersForAll_t*membersForAll)
 // looks for a match between a membership set and ABC dimensions currently checked
 {
 int mIx,aIx,tIx;
 for (aIx = dimA; aIx < membersForAll->dimMax; aIx++)  // for each ABC subGroup
     {
@@ -3180,46 +3156,46 @@
 return TRUE; // passed all tests so must be on all
 }
 
 char *compositeGroupLabel(struct trackDb *tdb, char *group, char *id)
 // Given ID from group, return corresponding label,  looking through parent's subGroupN's
 // Given group ID, return group label,  looking through parent's subGroupN's
 {
 members_t *members = subgroupMembersGet(tdb, group);
 char *result = NULL;
 int i;
 for (i=0; i<members->count; ++i)
     {
     if (sameString(members->tags[i], id))
 	result = cloneString(members->titles[i]);
     }
-subgroupMembersFree(&members);
+//subgroupMembersFree(&members);   /// don't bother freeing
 return result;
 }
 
 char *compositeGroupId(struct trackDb *tdb, char *group, char *label)
 // Given label, return id,  looking through parent's subGroupN's
 {
 members_t *members = subgroupMembersGet(tdb, group);
 char *result = NULL;
 int i;
 for (i=0; i<members->count; ++i)
     {
     if (sameString(members->titles[i], label))
 	result = cloneString(members->tags[i]);
     }
-subgroupMembersFree(&members);
+//subgroupMembersFree(&members);   /// don't bother freeing
 return result;
 }
 
 
 static boolean subtrackInAllCurrentABCs(struct trackDb *childTdb,membersForAll_t*membersForAll)
 // looks for a match between a membership set and ABC dimensions currently checked
 {
 membership_t *membership = subgroupMembershipGet(childTdb);
 if (membership == NULL)
     return FALSE;
 boolean found = membershipInAllCurrentABCs(membership,membersForAll);
 return found;
 }