4f46a97599aeb8374d4ff2b41a41edae1ce76ca5
tdreszer
  Mon Jul 25 15:28:04 2011 -0700
Replaced tdfbExtras hash with struct for efficiency. Redmine 4674.
diff --git src/hg/lib/hui.c src/hg/lib/hui.c
index d52391c..1364274 100644
--- src/hg/lib/hui.c
+++ src/hg/lib/hui.c
@@ -2153,84 +2153,83 @@
 }
 static void hierarchyFree(hierarchy_t **hierarchy)
 /* frees any previously obtained hierachy settings */
 {
 if(hierarchy && *hierarchy)
     {
     freeMem((*hierarchy)->setting);
     freeMem((*hierarchy)->membership);
     freeMem((*hierarchy)->indents);
     freez(hierarchy);
     }
 }
 
 // Four State checkboxes can be checked/unchecked by enable/disabled
 // NOTE: fourState is not a bitmap because it is manipulated in javascript and int seemed easier at the time
-#define FOUR_STATE_KEY               "fourState"
-#define FOUR_STATE_EMPTY             666
+#define FOUR_STATE_EMPTY             TDB_EXTRAS_EMPTY_STATE
 //#define FOUR_STATE_UNCHECKED         0
 //#define FOUR_STATE_CHECKED           1
 //#define FOUR_STATE_CHECKED_DISABLED  -1
 #define FOUR_STATE_DISABLE(val)      {while((val) >= 0) (val) -= 2;}
 #define FOUR_STATE_ENABLE(val)       {while((val) < 0) (val) += 2;}
 
 int subtrackFourStateChecked(struct trackDb *subtrack, struct cart *cart)
 /* Returns the four state checked state of the subtrack */
 {
 char * setting = NULL;
 char objName[SMALLBUF];
-int fourState = (int)(long)tdbExtrasGetOrDefault(subtrack,FOUR_STATE_KEY,(void *)FOUR_STATE_EMPTY);
+int fourState = (int)tdbExtrasFourState(subtrack);
 if(fourState != FOUR_STATE_EMPTY)
     return fourState;
 
 fourState = FOUR_STATE_UNCHECKED;  // default to unchecked, enabled
 if ((setting = trackDbLocalSetting(subtrack, "parent")) != NULL)
     {
     if(findWordByDelimiter("off",' ',setting) == NULL)
         fourState = FOUR_STATE_CHECKED;
     }
 
 // Now check visibility
 enum trackVisibility vis = tdbLocalVisibility(cart, subtrack, NULL);
 if (vis == tvHide)
     {
     if(tdbIsCompositeView(subtrack->parent))
         {
         if(tdbLocalVisibility(cart, subtrack->parent, NULL) == tvHide)
             FOUR_STATE_DISABLE(fourState);
         }
     }
 
 safef(objName, sizeof(objName), "%s_sel", subtrack->track);
 fourState = cartUsualInt(cart, objName, fourState);
-tdbExtrasAddOrUpdate(subtrack,FOUR_STATE_KEY,(void *)(long)fourState);
+tdbExtrasFourStateSet(subtrack,fourState);
 return fourState;
 }
 
 void subtrackFourStateCheckedSet(struct trackDb *subtrack, struct cart *cart,boolean checked, boolean enabled)
 /* Sets the fourState Checked in the cart and updates cached state */
 {
 int fourState = ( checked ? FOUR_STATE_CHECKED : FOUR_STATE_UNCHECKED );
 if (!enabled)
     FOUR_STATE_DISABLE(fourState);
 
 char objName[SMALLBUF];
 char objVal[5];
 safef(objName, sizeof(objName), "%s_sel", subtrack->track);
 safef(objVal, sizeof(objVal), "%d", fourState);
 cartSetString(cart, objName, objVal);
-tdbExtrasAddOrUpdate(subtrack,FOUR_STATE_KEY,(void *)(long)fourState);
+tdbExtrasFourStateSet(subtrack,fourState);
 }
 
 
 typedef struct _dimensions {
     int count;
     char**names;
     char**subgroups;
     char* setting;
 } dimensions_t;
 
 boolean dimensionsExist(struct trackDb *parentTdb)
 /* Does this parent track contain dimensions? */
 {
     return (trackDbSetting(parentTdb, "dimensions") != NULL);
 }
@@ -2621,35 +2620,34 @@
         if(ixOut < ixIn)  // Collapse if necessary
             { // NOTE: Don't I wish I had made these as an slList ages ago! (tim)
             membersForAll->members[ixOut]     = membersForAll->members[ixIn];
             membersForAll->checkedTags[ixOut] = membersForAll->checkedTags[ixIn];
             membersForAll->letters[ixOut]     = membersForAll->letters[ixIn];
             }
         ixOut++;
         }
     }
 membersForAll->dimMax   = ixOut;
 membersForAll->abcCount = membersForAll->dimMax - dimA;
 
 return membersForAll;
 }
 
-#define MEMBERS_FOR_ALL_KEY "membersForAll"
 static membersForAll_t* membersForAllSubGroupsGet(struct trackDb *parentTdb, struct cart *cart)
 /* Returns all the parents subGroups and members */
 {
-membersForAll_t *membersForAll =tdbExtrasGetOrDefault(parentTdb,MEMBERS_FOR_ALL_KEY,NULL);
+membersForAll_t *membersForAll = tdbExtrasMembersForAll(parentTdb);
 if(membersForAll != NULL)
     return membersForAll;  // Already retrieved, so don't do it again
 
 int ix;
 membersForAll = needMem(sizeof(membersForAll_t));
 membersForAll->members[dimV]=subgroupMembersGet(parentTdb,"view");
 membersForAll->letters[dimV]='V';
 membersForAll->dimMax=dimA;  // This can expand, depending upon ABC dimensions
 membersForAll->dimensions = dimensionSettingsGet(parentTdb);
 if(membersForAll->dimensions != NULL)
     {
     for(ix=0;ix<membersForAll->dimensions->count;ix++)
         {
         char letter = lastChar(membersForAll->dimensions->names[ix]);
         if(letter != 'X' && letter != 'Y')
@@ -2703,31 +2701,31 @@
             char letter = lastChar(dim);
             int abcIx = dimA;
             for (;abcIx < membersForAll->dimMax && membersForAll->letters[abcIx] != letter;abcIx++) ; // Advance to correct letter
             if (abcIx >= membersForAll->dimMax)
                 errAbort("Invalid 'filterComposite' trackDb setting. Dimension '%s' not found.",dim);
             if (sameWord(filterGroups[ix],"one"))
                 membersForAll->members[abcIx]->fcType = fctOne;
             else if (sameWord(filterGroups[ix],"onlyOne") || sameWord(filterGroups[ix],"oneOnly"))
                 membersForAll->members[abcIx]->fcType = fctOneOnly;
             }
         }
 #endif///def FILTER_COMPOSITE_ONLYONE
     }
 
 if(cart != NULL) // Only save this if it is fully populated!
-    tdbExtrasAddOrUpdate(parentTdb,MEMBERS_FOR_ALL_KEY,membersForAll);
+    tdbExtrasMembersForAllSet(parentTdb,membersForAll);
 
 return membersForAll;
 }
 
 static int membersForAllFindSubGroupIx(membersForAll_t* membersForAll, char *tag)
 { // Returns the index of the subgroups member struct within membersForAll (or -1)
 int ix = 0;
 for(ix=0;ix<membersForAll->dimMax;ix++)
     {
     if (membersForAll->members[ix] != NULL && sameString(membersForAll->members[ix]->groupTag,tag))
         return ix;
     }
 return -1;
 }
 
@@ -2738,31 +2736,31 @@
     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 */
 {
 if(membersForAllPtr && *membersForAllPtr)
     {
     if(parentTdb != NULL)
         {
-        if(*membersForAllPtr == tdbExtrasGetOrDefault(parentTdb,MEMBERS_FOR_ALL_KEY,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);
         subgroupMembersFree(&(membersForAll->members[ix]));
         if(membersForAll->checkedTags[ix])
             freeMem(membersForAll->checkedTags[ix]);
         }
     dimensionsFree(&(membersForAll->dimensions));
@@ -2781,35 +2779,34 @@
 int cnt;
 char *words[32];
 cnt = chopLine(setting, words);
 freeMem(setting);
 return (cnt - 1);
 }
 
 typedef struct _membership {
     int count;
     char **subgroups;    // Ary of Tags in parentTdb->subGroupN and in childTdb->subGroups (ie view)
     char **membership;   // Ary of Tags of subGroups that child belongs to (ie PK)
     char **titles;       // Ary of Titles of subGroups a child belongs to (ie Peak)
     char * setting;
 } membership_t;
 
-#define SUBTRACK_MEMBERSHIP_KEY "subgroupMembership"
 static membership_t *subgroupMembershipGet(struct trackDb *childTdb)
 /* gets all the subgroup membership for a child track */
 {
-membership_t *membership = tdbExtrasGetOrDefault(childTdb,SUBTRACK_MEMBERSHIP_KEY,NULL);
+membership_t *membership = tdbExtrasMembership(childTdb);
 if(membership != NULL)
     return membership;  // Already retrieved, so don't do it again
 
 membership = needMem(sizeof(membership_t));
 membership->setting = cloneString(trackDbSetting(childTdb, "subGroups"));
 if(membership->setting == NULL)
     {
     freeMem(membership);
     return NULL;
     }
 
 int ix,cnt;
 char *words[SMALLBUF];
 cnt = chopLine(membership->setting, words);
 assert(cnt <= ArraySize(words));
@@ -2829,31 +2826,31 @@
         {
         membership->subgroups[membership->count]  = name;
         membership->membership[membership->count] = value;//strSwapChar(value,'_',' ');
         members_t* members = subgroupMembersGet(childTdb->parent, name);
         membership->titles[membership->count] = NULL; // default
         if(members != NULL)
             {
             int ix2 = stringArrayIx(value,members->tags,members->count);
             if(ix2 != -1)
                 membership->titles[membership->count] = strSwapChar(cloneString(members->titles[ix2]),'_',' ');
             subgroupMembersFree(&members);
             }
         membership->count++;
         }
     }
-tdbExtrasAddOrUpdate(childTdb,SUBTRACK_MEMBERSHIP_KEY,membership);
+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
     {
     assert(membersForAll->members[aIx]->selected);
 
     // must find atleast one selected tag that we have membership in
     boolean matched = FALSE;
     for (mIx = 0; mIx <membersForAll->members[aIx]->count;mIx++) // for each tag of that subgroup
@@ -2865,47 +2862,30 @@
                 if(sameString(membersForAll->members[aIx]->groupTag, membership->subgroups[tIx])   // subTrack belongs to subGroup
                 &&   sameWord(membersForAll->members[aIx]->tags[mIx],membership->membership[tIx])) // and tags match
                     {
                     matched = TRUE;
                     break;
                     }
                 }
             }
         }
         if(!matched)
             return FALSE;
     }
 return TRUE; // passed all tests so must be on all
 }
 
-// No longer free this because it is saved in subtrack tdbExtras
-#define subgroupMembershipFree(membership)
-//static void subgroupMembershipFree(membership_t **membership)
-//// frees subgroupMembership memory
-//{
-//if(membership && *membership)
-//    {
-//    int ix;
-//    for(ix=0;ix<(*membership)->count;ix++) { freeMem((*membership)->titles[ix]); }
-//    freeMem((*membership)->titles);
-//    freeMem((*membership)->setting);
-//    freeMem((*membership)->subgroups);
-//    freeMem((*membership)->membership);
-//    freez(membership);
-//    }
-//}
-
 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);
 return result;
 }
@@ -2921,31 +2901,30 @@
     if (sameString(members->titles[i], label))
 	result = cloneString(members->tags[i]);
     }
 subgroupMembersFree(&members);
 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);
-subgroupMembershipFree(&membership);
 return found;
 }
 
 
 boolean subgroupFind(struct trackDb *childTdb, char *name,char **value)
 /* looks for a single tag in a child track's subGroups setting */
 {
 if(value != NULL)
     *value = NULL;
 membership_t *membership = subgroupMembershipGet(childTdb);
 if(membership != NULL)
     {
     int ix;
     for(ix=0;ix<membership->count;ix++)
         {
@@ -4165,31 +4144,30 @@
     if (restrictions)
         {
         char *dateDisplay = encodeRestrictionDateDisplay(db,subtrack);
         if (dateDisplay)
             {
             if (dateIsOld(dateDisplay,"%F"))
                 printf("</TD>\n<TD align='center' nowrap style='color: #BBBBBB;'>&nbsp;%s&nbsp;", dateDisplay);
             else
                 printf("</TD>\n<TD align='center'>&nbsp;%s&nbsp;", dateDisplay);
             }
         }
 
     // End of row and free ourselves of this subtrack
     puts("</TD></TR>\n");
     checkBoxIdFree(&id);
-    subgroupMembershipFree(&membership);
     }
 
 // End of the table
 puts("</TBODY>");
 if (slCount(subtrackRefList) > 5 || (restrictions && sortOrder != NULL))
     {
     printf("<TFOOT style='background-color:%s;'><TR valign='top'><TD colspan=%d>&nbsp;&nbsp;&nbsp;&nbsp;",
            COLOR_BG_DEFAULT_DARKER,columnCount-1);
 
     // Count of subtracks is filled in by javascript.
     if (slCount(subtrackRefList) > 5)
         printf("<span class='subCBcount'></span>\n");
 
     // Restruction policy needs a link
     if (restrictions && sortOrder != NULL)