cf2bb7881c445dcf901c5b2d770aa90995e18fa7
tdreszer
  Fri Jun 10 13:19:57 2011 -0700
downloadsOnly tracks will continue to have a 'table' value, even though that is meaningless.  This is because CGIs need bullet-proofing.  I have done hgTracks, hgTrackUi, hgTables and hgGenome.
diff --git src/hg/lib/hdb.c src/hg/lib/hdb.c
index c761050..db9aac3 100644
--- src/hg/lib/hdb.c
+++ src/hg/lib/hdb.c
@@ -833,41 +833,45 @@
 tableNames = (struct slName *)hashFindVal(hash, trackName);
 for (tbl = tableNames;  tbl != NULL;  tbl = tbl->next)
     {
     if (sameString(table, tbl->name))
 	return TRUE;
     }
 return FALSE;
 }
 
 char *hTableForTrack(char *db, char *trackName)
 /* Return a table for a track in db. Returns one of the split
  * tables, or main table if not split.
  * In addition, caches all the tracks and tables in db the first
  * time it is called (could be many thousand tables). */
 {
+if (trackName == NULL)
+    return NULL;
 struct hash *hash = tableListGetDbHash(db);
 struct slName *tableNames = NULL;
 tableNames = (struct slName *)hashFindVal(hash, trackName);
 if (tableNames != NULL)
     return tableNames->name;
 return NULL;
 }
 
 boolean hTableOrSplitExists(char *db, char *track)
 /* Return TRUE if track table (or split table) exists in db. */
 {
+if (track == NULL)
+    return FALSE;
 if (!hDbExists(db))
     return FALSE;
 struct hash *hash = tableListGetDbHash(db);
 return (hashLookup(hash, track) != NULL);
 }
 
 void hParseTableName(char *db, char *table, char trackName[HDB_MAX_TABLE_STRING],
 		     char chrom[HDB_MAX_CHROM_STRING])
 /* Parse an actual table name like "chr17_random_blastzWhatever" into
  * the track name (blastzWhatever) and chrom (chr17_random). */
 /* Note: for the sake of speed, this does not consult chromInfo
  * because that would be extremely slow for scaffold-based dbs.
  * Instead this makes some assumptions about chromosome names and split
  * table names in databases that support split tables, and just parses text.
  * When chromosome/table name conventions change, this will need an update! */
@@ -3471,34 +3475,38 @@
 
 static boolean trackDataAccessible(char *database, struct trackDb *tdb)
 /* Return TRUE if data accessible - meaning either it has a bigDataUrl, or the
  * table exists. */
 {
 return trackDbSetting(tdb, "bigDataUrl") != NULL || hTableForTrack(database, tdb->table) != NULL;
 }
 
 static void addTrackIfDataAccessible(char *database, struct trackDb *tdb,
 	       boolean privateHost, struct trackDb **tdbRetList)
 /* check if a trackDb entry should be included in display, and if so
  * add it to the list, otherwise free it */
 {
 if ((!tdb->private || privateHost) && trackDataAccessible(database, tdb))
     slAddHead(tdbRetList, tdb);
-else if (sameWord(tdb->type,"downloadsOnly"))
-    {
-    if (sameString(tdb->table,tdb->track))
-        tdb->table = NULL;
+else if (tdbIsDownloadsOnly(tdb))
+    {
+    // While it would be good to make table NULL, since we should support tracks
+    // without tables (composties, etc) and even data tracks without tables (bigWigs).
+    // However, some CGIs still need careful bullet-proofing.  I have done so with
+    //   hgTrackUi, hgTracks, hgTable and hgGenome
+    //if (tdb->table != NULL && sameString(tdb->table,tdb->track))
+    //    tdb->table = NULL;
     slAddHead(tdbRetList, tdb);
     }
 else
     trackDbFree(&tdb);
 }
 
 #ifdef UNUSED
 static void inheritFieldsFromParents(struct trackDb *tdb, struct trackDb *parent)
 /* Inherit undefined fields (outside of settings) from parent. */
 {
 if (tdb->shortLabel == NULL)
     tdb->shortLabel = cloneString(parent->shortLabel);
 if (tdb->type == NULL)
     tdb->type = cloneString(parent->type);
 if (tdb->longLabel == NULL)
@@ -3686,30 +3694,43 @@
 rInheritFields(tdbList);
 slSort(&tdbList, trackDbCmp);
 return tdbList;
 }
 
 struct trackDb *hTrackDb(char *db)
 /* Load tracks associated with current db.
  * Supertracks are loaded as a trackDb, but are not in the returned list,
  * but are accessible via the parent pointers of the member tracks.  Also,
  * the supertrack trackDb subtrack fields are not set here (would be
  * incompatible with the returned list)
  * Returns list sorted by priority
  *	NOTE: this result is cached, do not free it !
  */
 {
+// FIXME: This is NOT CACHED and should be!  Since some callers (e.g. hgTables) consume the list,
+// I would suggest:
+// 1) static hash by db/hub
+// 2) call creates list if not in hash
+// 3) static (to this file) routine gives the actual tdb list
+// 4) public lib routine that returns fully cloned list
+// 5) public lib routine that returns cloned individual tdb complete with up/down inheritance
+// UNFORTUNATELY, cloning the memory with prove costly in time as well, because of all the pointers
+// to relink.  THEREFORE what should be done is to make the tdb list with const ->next pointers and
+// force discpline on the callers.  Sorts should be by hdb.c routines and any new lists (such as
+// hgTables makes) should be via tdbRefs.
+// SO we are back to being STALLED because of the volume of work.
+
 // static char *existingDb = NULL;
 // static struct trackDb *tdbList = NULL;
 struct trackDb *tdbList = NULL;
 //if (differentStringNullOk(existingDb, db))
 //    {
     tdbList = loadTrackDb(db, NULL);
     tdbList = trackDbLinkUpGenerations(tdbList);
     tdbList = trackDbPolishAfterLinkup(tdbList, db);
 //    freeMem(existingDb);
 //    existingDb = cloneString(db);
 //    }
 return tdbList;
 }
 
 static struct trackDb *loadAndLookupTrackDb(struct sqlConnection *conn,