ec4aa63c0938b8166f55a9cab045e12827685742 kent Tue Jul 19 13:50:10 2011 -0700 Optimizing parentChildCartCleanup by creating a faster version of cartVarsWithPrefix that works in local memory. diff --git src/hg/lib/cart.c src/hg/lib/cart.c index 15080fe..d875ee8 100644 --- src/hg/lib/cart.c +++ src/hg/lib/cart.c @@ -846,30 +846,56 @@ struct slPair *cartVarsWithPrefix(struct cart *cart, char *prefix) /* Return a slPair list of cart vars that begin with prefix */ { struct slPair *cartVars = NULL; struct hashEl *el, *elList = hashElListHash(cart->hash); slSort(&elList, hashElCmp); for (el = elList; el != NULL; el = el->next) { if (startsWith(prefix, el->name)) slAddHead(&cartVars,slPairNew(el->name,el->val)); } hashElFreeList(&elList); return cartVars; } +struct slPair *cartVarsWithPrefixLm(struct cart *cart, char *prefix, struct lm *lm) +/* Return list of cart vars that begin with prefix allocated in local memory. + * Quite a lot faster than cartVarsWithPrefix. */ +{ +struct slPair *cartVars = NULL; +struct hash *hash = cart->hash; +int hashSize = hash->size; +struct hashEl *hel; +int i; +for (i=0; i<hashSize; ++i) + { + for (hel = hash->table[i]; hel != NULL; hel = hel->next) + { + if (startsWith(prefix, hel->name)) + { + struct slPair *pair; + lmAllocVar(lm, pair); + pair->name = lmCloneString(lm, hel->name); + pair->val = lmCloneString(lm, hel->val); + slAddHead(&cartVars, pair); + } + } + } +return cartVars; +} + void cartRemoveLike(struct cart *cart, char *wildCard) /* Remove all variable from cart that match wildCard. */ { struct slPair *cartVars = cartVarsLike(cart,wildCard); while(cartVars != NULL) { struct slPair *cartVar = slPopHead(&cartVars); cartRemove(cart, cartVar->name); freeMem(cartVar); } } void cartRemovePrefix(struct cart *cart, char *prefix) /* Remove variables with given prefix from cart. */ { @@ -1941,47 +1967,46 @@ return (!ignoreRemoved); #ifdef CART_DIFFS_INCLUDE_EMPTIES if (sameString(oldValue,CART_VAR_EMPTY)) { if (sameString(newValue,"hide") || sameString(newValue,"off") || sameString(newValue,"0")) // Special cases DANGER! return FALSE; } #endif///def CART_DIFFS_INCLUDE_EMPTIES return (differentString(newValue,oldValue)); } -int cartNamesPruneChanged(struct cart *newCart,struct hash *oldVars, +static int cartNamesPruneChanged(struct cart *newCart,struct hash *oldVars, struct slPair **cartNames,boolean ignoreRemoved,boolean unChanged) /* Prunes a list of cartNames if the settings have changed between new and old cart. Returns pruned count */ { int pruned = 0; struct slPair *oldList = *cartNames; struct slPair *newList = NULL; struct slPair *oneName = NULL; while ((oneName = slPopHead(&oldList)) != NULL) { boolean thisOneChanged = cartValueHasChanged(newCart,oldVars,oneName->name,ignoreRemoved,TRUE); if (unChanged != thisOneChanged) slAddHead(&newList,oneName); else { - freeMem(oneName); pruned++; } } *cartNames = newList; return pruned; } int cartRemoveFromTdbTree(struct cart *cart,struct trackDb *tdb,char *suffix,boolean skipParent) /* Removes a 'trackName.suffix' from all tdb descendents (but not parent). If suffix NULL then removes 'trackName' which holds visibility */ { int removed = 0; boolean vis = (suffix == NULL || *suffix == '\0'); struct slRef *tdbRef, *tdbRefList = trackDbListGetRefsToDescendants(skipParent?tdb->subtracks:tdb); @@ -2257,31 +2282,31 @@ } } else // If no views then composite is not set to fuul but to max of subtracks count = cartTdbParentShapeVis(cart,tdbContainer,NULL,subVisHash,reshapeFully); hashFree(&subVisHash); // If reshaped, be sure to set flag to stop composite cleanup #define RESHAPED_COMPOSITE "reshaped" if (count > 0) tdbExtrasAddOrUpdate(tdbContainer,RESHAPED_COMPOSITE,(void *)(long)TRUE); // Exists for the life of the cgi only return TRUE; } -boolean cartTdbTreeCleanupOverrides(struct trackDb *tdb,struct cart *newCart,struct hash *oldVars) +boolean cartTdbTreeCleanupOverrides(struct trackDb *tdb,struct cart *newCart,struct hash *oldVars, struct lm *lm) /* When container or composite/view settings changes, remove subtrack specific settings Returns TRUE if any cart vars are removed */ { boolean anythingChanged = cartTdbOverrideSuperTracks(newCart,tdb,TRUE); if (!tdbIsContainer(tdb)) return anythingChanged; // If composite has been reshaped then don't clean it up if ((boolean)(long)tdbExtrasGetOrDefault(tdb,RESHAPED_COMPOSITE,(void *)(long)FALSE)) return anythingChanged; // vis is a special additive case! composite or view level changes then remove subtrack vis boolean containerVisChanged = cartValueHasChanged(newCart,oldVars,tdb->track,TRUE,FALSE); if (containerVisChanged) { @@ -2289,39 +2314,39 @@ char *cartVis = cartOptionalString(newCart,tdb->track); char *oldValue = hashFindVal(oldVars,tdb->track); if (cartVis && oldValue == NULL && hTvFromString(cartVis) == tdb->visibility) containerVisChanged = FALSE; } struct trackDb *tdbView = NULL; struct slPair *oneName = NULL; char *suffix = NULL; int clensed = 0; // Build list of current settings for container or composite and views char setting[512]; safef(setting,sizeof(setting),"%s.",tdb->track); char * view = NULL; boolean hasViews = FALSE; -struct slPair *changedSettings = cartVarsWithPrefix(newCart, setting); +struct slPair *changedSettings = cartVarsWithPrefixLm(newCart, setting, lm); for (tdbView = tdb->subtracks;tdbView != NULL; tdbView = tdbView->next) { if (!tdbIsView(tdbView,&view)) break; hasViews = TRUE; safef(setting,sizeof(setting),"%s.",tdbView->track); // unfortunatly setting name could be viewTrackName.??? //safef(setting, sizeof(setting),"%s.%s.",tdb->track,view); // or containerName.Sig.??? HOWEVER: this are picked up by containerName prefix - struct slPair *changeViewSettings = cartVarsWithPrefix(newCart, setting); + struct slPair *changeViewSettings = cartVarsWithPrefixLm(newCart, setting, lm); changedSettings = slCat(changedSettings, changeViewSettings); } if (changedSettings == NULL && !containerVisChanged) return anythingChanged; // Prune list to only those which have changed if(changedSettings != NULL) { (void)cartNamesPruneChanged(newCart,oldVars,&changedSettings,TRUE,FALSE); if (changedSettings == NULL && !containerVisChanged) return anythingChanged; } // Walk through views if (hasViews) @@ -2344,59 +2369,57 @@ else if(startsWith(settingAlt,oneName->name)) suffix = oneName->name + strlen(settingAlt); else { slAddHead(&leftOvers,oneName); continue; } if (sameString(suffix,"vis")) { viewVisChanged = TRUE; } else if (cartRemoveOldFromTdbTree(newCart,oldVars,tdbView,suffix,oneName->val,TRUE) > 0) clensed++; - freeMem(oneName); } if (viewVisChanged) { // If just created and if vis is the same as tdb default then vis has not changed safef(setting,sizeof(setting),"%s.%s.vis",tdb->track,view); char *cartVis = cartOptionalString(newCart,setting); char *oldValue = hashFindVal(oldVars,setting); if (cartVis && oldValue == NULL && hTvFromString(cartVis) != tdbView->visibility) viewVisChanged = FALSE; } if (containerVisChanged || viewVisChanged) { // vis is a special additive case! WARN("Removing subtrack vis for %s.%s",tdb->track,view); char *viewVis = hStringFromTv(tdbVisLimitedByAncestry(newCart, tdbView, FALSE)); if (cartRemoveOldFromTdbTree(newCart,oldVars,tdbView,NULL,viewVis,TRUE) > 0) clensed++; } changedSettings = leftOvers; } } // Now deal with anything remaining at the container level while ((oneName = slPopHead(&changedSettings)) != NULL) { suffix = oneName->name + strlen(tdb->track) + 1; if (cartRemoveOldFromTdbTree(newCart,oldVars,tdb,suffix,oneName->val,TRUE) > 0) clensed++; - freeMem(oneName); } if (containerVisChanged && !hasViews) { // vis is a special additive case! char *vis = hStringFromTv(tdbVisLimitedByAncestry(newCart, tdb, FALSE)); if (cartRemoveOldFromTdbTree(newCart,oldVars,tdb,NULL,vis,TRUE) > 0) clensed++; } anythingChanged = (anythingChanged || (clensed > 0)); return anythingChanged; }