src/hg/makeDb/hgTrackDb/hgTrackDb.c 1.59

1.59 2010/01/09 20:54:15 galt
release alpha/beta was broken. Now that closest-to-home has gone away, it was very easy to implement very-early release pruning, followed later by pruning of orphans with no parent of the correct release. This keeps the code pretty simple which is nice.
Index: src/hg/makeDb/hgTrackDb/hgTrackDb.c
===================================================================
RCS file: /projects/compbio/cvsroot/kent/src/hg/makeDb/hgTrackDb/hgTrackDb.c,v
retrieving revision 1.58
retrieving revision 1.59
diff -b -B -U 4 -r1.58 -r1.59
--- src/hg/makeDb/hgTrackDb/hgTrackDb.c	6 Jan 2010 21:48:19 -0000	1.58
+++ src/hg/makeDb/hgTrackDb/hgTrackDb.c	9 Jan 2010 20:54:15 -0000	1.59
@@ -61,9 +61,9 @@
 static char *release = "alpha";
 static bool showSettings = FALSE;
 
 static boolean hasNonAsciiChars(char *text)
-/* check if text has any non-printing or non-ascii characters */
+/* Check if text has any non-printing or non-ascii characters */
 {
 char *c;
 for (c = text; *c != '\0'; c++)
     {
@@ -76,9 +76,9 @@
 }
 
 
 static struct trackDb *trackDbListFromHash(struct hash *tdHash)
-/* build a list of the tracks in hash.  List will be threaded through
+/* Build a list of the tracks in hash.  List will be threaded through
  * the entries. */
 {
 struct trackDb *tdbList = NULL;
 struct hashCookie cookie = hashFirst(tdHash);
@@ -115,40 +115,8 @@
 slReverse(&newList);
 return newList;
 }
 
-static boolean releasesCompatible(struct trackDb *a, struct trackDb *b)
-/* Return TRUE if either release is NULL, or if they both exist and match. */
-{
-char *aRelease = trackDbSetting(a, "release");
-char *bRelease = trackDbSetting(b, "release");
-return aRelease == NULL || bRelease == NULL || sameString(aRelease, bRelease);
-}
-
-static void fillInSubtrackParentsRespectingRelease(struct trackDb *tdbList, struct hash *trackHash)
-/* Fill in parent pointers. This just handles a part of the heirarchy, but it does handle releases. */
-{
-/* Loop through looking for parent tracks whenever see the subTrack tag. 
- * Try to find parent just in compatible release. */
-struct trackDb *td;
-for (td = tdbList; td != NULL; td = td->next)
-    {
-    char *parentName = trackDbLocalSetting(td, "subTrack");
-    if (parentName != NULL)
-        {
-	struct hashEl *hel;
-	for (hel = hashLookup(trackHash, parentName); hel != NULL; hel = hashLookupNext(hel))
-	    {
-	    struct trackDb *p = hel->val;
-	    if (releasesCompatible(p, td))
-		{
-	        td->parent = p;
-		break;
-		}
-	    }
-	}
-    }
-}
 
 static struct trackDb *pruneEmptyContainers(struct trackDb *tdbList)
 /* Remove container tracks (views and compositeTracks) with no children. */
 {
@@ -173,14 +141,11 @@
 slReverse(&newList);
 return newList;
 }
 
-static struct trackDb * pruneRelease(struct trackDb *tdbList, struct hash *trackHash)
-/* prune out alternate track entries for another release */
+static struct trackDb * pruneRelease(struct trackDb *tdbList)
+/* Prune out alternate track entries for another release */
 {
-/* Link up parents so that trackDbSettingClosest to home will work. */
-fillInSubtrackParentsRespectingRelease(tdbList, trackHash);
-
 /* Build up list that only includes things in this release.  Release
  * can be inherited from parents. */
 struct trackDb *tdb;
 struct trackDb *relList = NULL;
@@ -188,27 +153,57 @@
     {
     char *rel = trackDbSetting(tdb, "release");
     if (rel == NULL || sameString(rel, release))
 	{
-	verbose(3,"pruneRelease: adding '%s', release: '%s' =? '%s'\n",
-	    tdb->tableName, rel, release);
+	/* Remove release tags in remaining tracks, since its purpose is served. */
+	hashRemove(tdb->settingsHash, "release");
 	slAddHead(&relList, tdb);
 	}
     else
 	verbose(3,"pruneRelease: removing '%s', release: '%s' != '%s'\n",
 	    tdb->tableName, rel, release);
     }
-
-/* Remove release tags in remaining tracks, since its purpose is served. */
-for (tdb = relList; tdb != NULL; tdb = tdb->next)
-    hashRemove(tdb->settingsHash, "release");
-
 return relList;
 }
 
+static struct trackDb * pruneOrphans(struct trackDb *tdbList, struct hash *trackHash)
+/* Prune out orphans with no parents of the right release */
+{
+boolean done = FALSE;
+struct trackDb *tdb;
+struct trackDb *nonOrphanList = NULL;
+while (!done)
+    {
+    done = TRUE;
+    nonOrphanList = NULL;
+    while ((tdb = slPopHead(&tdbList)) != NULL)
+	{
+	char *parentName = trackDbLocalSetting(tdb, "subTrack");
+	struct hashEl *hel = NULL;
+	if (parentName != NULL)
+	    {
+	    hel = hashLookup(trackHash, parentName);
+	    }
+	if (parentName == NULL || hel != NULL)
+	    {
+	    slAddHead(&nonOrphanList, tdb);
+	    }
+	else
+	    {
+	    verbose(3,"pruneOrhans: removing '%s'\n",
+		tdb->tableName);
+	    hashRemove(trackHash, tdb->tableName);
+	    done = FALSE;
+	    }
+	}
+    tdbList = nonOrphanList;
+    }
+return tdbList;
+}
+
 static void applyOverride(struct hash *trackHash,
                           struct trackDb *overTd)
-/* apply a trackDb override to a track, if it exists */
+/* Apply a trackDb override to a track, if it exists */
 {
 struct trackDb *tdb = hashFindVal(trackHash, overTd->tableName);
 if (tdb != NULL)
     trackDbOverride(tdb, overTd);
@@ -219,23 +214,19 @@
 /* Read in tracks from raName and add them to table, pruning as required. Call
  * top-down so that track override will work. */
 {
 struct trackDb *tdbList = trackDbFromRa(raName), *tdb;
+/* prune records of the incorrect release */
+tdbList= pruneRelease(tdbList);
 
 /* load tracks, replacing higher-level ones with lower-level and
  * applying overrides*/
 while ((tdb = slPopHead(&tdbList)) != NULL)
     {
     if (tdb->overrides != NULL)
         applyOverride(trackHash, tdb);
     else
-	{
-	struct hashEl *hel = hashLookup(trackHash, tdb->tableName);
-	if (hel != NULL)
-	    verbose(2,"addVersionRa: warning duplicate tableName: '%s'\n",
-		tdb->tableName);
-	hashAdd(trackHash, tdb->tableName, tdb);
-	}
+	hashStore(trackHash, tdb->tableName)->val = tdb;
     }
 }
 
 void updateBigTextField(struct sqlConnection *conn, char *table,
@@ -309,9 +300,9 @@
 for (td = tdbList; td != NULL; td = td->next)
     {
     if (isEmpty(td->html))
         {
-        char *htmlName = trackDbSettingClosestToHome(td, "html");
+        char *htmlName = trackDbSetting(td, "html");
         if (htmlName == NULL)
             htmlName = td->tableName;
 	safef(fileName, sizeof(fileName), "%s/%s.html", dirName, htmlName);
 	if (fileExists(fileName))
@@ -472,18 +463,18 @@
     }
 }
 
 static void checkSubGroups(struct trackDb *tdbList)
-/* check integrity of subGroup clauses */
+/* Check integrity of subGroup clauses */
 {
 struct hash *compositeHash = buildCompositeHash(tdbList);
 
 verifySubTracks(tdbList, compositeHash);
 }
 
 
 static void prioritizeContainerItems(struct trackDb *tdbList)
-/* set priorities in containers if they have no priorities already set
+/* Set priorities in containers if they have no priorities already set
    priorities are based upon 'sortOrder' setting or else shortLabel */
 {
 int countOfSortedContainers = 0;
 
@@ -605,9 +596,9 @@
 
 static struct trackDb *buildTrackDb(char *org, char *database, char *hgRoot,
                                     char *visibilityRa, char *priorityRa,
                                     boolean strict)
-/* build trackDb objects from files. */
+/* Build trackDb objects from files. */
 {
 struct hash *trackHash = newHash(0);
 char rootDir[PATH_LEN], orgDir[PATH_LEN], asmDir[PATH_LEN];
 
@@ -617,9 +608,10 @@
 safef(rootDir, sizeof(rootDir), "%s", hgRoot);
 safef(orgDir, sizeof(orgDir), "%s/%s", hgRoot, org);
 safef(asmDir, sizeof(asmDir), "%s/%s/%s", hgRoot, org, database);
 
-// must call these top-down
+/* Must call these top-down.
+ * Also prunes things not in our release. */
 layerOnRa(strict, database, rootDir, trackHash, TRUE);
 layerOnRa(strict, database, orgDir, trackHash, FALSE);
 layerOnRa(strict, database, asmDir, trackHash, FALSE);
 
@@ -629,12 +621,15 @@
 if (priorityRa != NULL)
     trackDbOverridePriority(trackHash, priorityRa);
 #endif /* OLD */
 
-/* Represent as list as well as hash, and prune things not in our release from list. 
- * After this hash is no longer userful since it contains pruned things, so get rid of it. */
+/* Represent hash as list */
 struct trackDb *tdbList = trackDbListFromHash(trackHash);
-tdbList= pruneRelease(tdbList, trackHash);
+
+/* Get rid of orphans with no parent of the correct release. */
+tdbList = pruneOrphans(tdbList, trackHash);
+
+/* After this the hash is no longer needed, so get rid of it. */
 hashFree(&trackHash);
 
 /* Read in HTML bits onto what remains. */
 layerOnHtml(asmDir, tdbList);