01dd700b0b41f2e24a587722bc68fe931283ae05
tdreszer
  Tue Oct 25 17:27:57 2011 -0700
No functional change.  Just better commenting and some name changing as requested by Brian in code review.
diff --git src/hg/lib/fileUi.c src/hg/lib/fileUi.c
index 72972a1..a4afa16 100644
--- src/hg/lib/fileUi.c
+++ src/hg/lib/fileUi.c
@@ -20,96 +20,87 @@
 {
 while (pFileList && *pFileList)
     {
     struct fileDb *oneFile = slPopHead(pFileList);
 
     freeMem(oneFile->fileName);
     freeMem(oneFile->fileType);
     freeMem(oneFile->fileDate);
     freeMem(oneFile->sortFields);
     freeMem(oneFile->reverse);
     mdbObjsFree(&(oneFile->mdb));
     freeMem(oneFile);
     }
 }
 
-static struct fileDb *fileDbReadFromCache(char *db, char *dir, char *subDir)
+static struct fileDb *fileDbReadFromBackup(char *db, char *dir, char *subDir)
 {
-struct tempName cacheFile;
-boolean exists = trashDirReusableFile(&cacheFile, dir, subDir, db);  // encodeDCC/composite.db
+struct tempName buFile;
+boolean exists = trashDirReusableFile(&buFile, dir, subDir, db);  // encodeDCC/composite.db
 if (!exists)
     return NULL;
-//warn("Reading: %s",cacheFile.forCgi);
 
 struct fileDb *fileList = NULL;
 struct fileDb *oneFile = NULL;
-struct lineFile *lf = lineFileOpen(cacheFile.forCgi, TRUE);
+struct lineFile *lf = lineFileOpen(buFile.forCgi, TRUE);
 char *words[4];
 while (lineFileChop(lf, words) >= 3)
     {
     AllocVar(oneFile);
     oneFile->fileName = cloneString(words[0]);
     oneFile->fileSize = sqlUnsignedLong(words[1]);
     oneFile->fileDate = cloneString(words[2]);
     slAddHead(&fileList,oneFile);
     }
 lineFileClose(&lf);
 if (fileList == NULL)
-    unlink(cacheFile.forCgi);    // remove empty file
+    unlink(buFile.forCgi);    // remove empty file
 
 return fileList;
 }
 
 // Cache is not faster, so just use it as a backup
 //#define CACHE_IS_FASTER_THAN_RSYNC
 #ifdef CACHE_IS_FASTER_THAN_RSYNC
-static boolean fileDbCacheAvailable(char *db, char *dir, char *subDir)
+static boolean fileDbBackupAvailable(char *db, char *dir, char *subDir)
 { // Checks if there is a recent enough cache file
   // TODO: Add some other trick to invalidate cache at will.
-struct tempName cacheFile;
-boolean exists = trashDirReusableFile(&cacheFile, dir, subDir, db);  // encodeDCC/composite.db
+struct tempName buFile;
+boolean exists = trashDirReusableFile(&buFile, dir, subDir, db);  // encodeDCC/composite.db
 if (exists)
     {
-    //char *clearCache = cartOptionalString(cart,"clearCache");  // where is cart coming from?
-    //if (clearCache && sameWord(clearCache,subDir))
-    //    {
-    //    cartRemove(cart,"clearCache");
-    //    unlink(cacheFile.forCgi);    // remove empty file
-    //    return FALSE;
-    //    }
     struct stat mystat;
     ZeroVar(&mystat);
-    if (stat(cacheFile.forCgi,&mystat)==0)
+    if (stat(buFile.forCgi,&mystat)==0)
         {
         // how old is old?
         int secs = (clock1() - mystat.st_ctime); // seconds since created
         if (secs < (24 * 60 * 60)) // one date
             return TRUE;
         }
     }
 return FALSE;
 }
 #endif///def CACHE_IS_FASTER_THAN_RSYNC
 
-static void fileDbWriteToCache(char *db, char *dir, char *subDir,struct fileDb *fileList)
+static void fileDbWriteToBackup(char *db, char *dir, char *subDir,struct fileDb *fileList)
 {
-struct tempName cacheFile;
-(void)trashDirReusableFile(&cacheFile, dir, subDir, db);  // encodeDCC/composite.db
-//warn("Writing: %s",cacheFile.forCgi);
+struct tempName buFile;
+(void)trashDirReusableFile(&buFile, dir, subDir, db);  // encodeDCC/composite.db
 
 FILE *fd = NULL;
-if ((fd = fopen(cacheFile.forCgi, "w")) != NULL)
+if ((fd = fopen(buFile.forCgi, "w")) != NULL)
     {
     struct fileDb *oneFile = fileList;
     for(;oneFile != NULL;oneFile=oneFile->next)
         {
         char buf[1024];
         safef(buf,sizeof buf,"%s %ld %s\n",oneFile->fileName,oneFile->fileSize,oneFile->fileDate);
         fwrite(buf, strlen(buf), 1, fd);
         }
     fclose(fd);
     }
 }
 
 struct fileDb *fileDbGet(char *db, char *dir, char *subDir, char *fileName)
 // Returns NULL or if found a fileDb struct with name, size and date filled in.
 {
@@ -118,34 +109,32 @@
 static char *savedSubDir = NULL;
 static struct fileDb *foundFiles = NULL;// Use static list to save excess IO
 struct fileDb *oneFile = NULL;
 if (foundFiles == NULL
 ||  savedDb  == NULL    || differentString(savedDb, db)
 ||  savedDir == NULL    || differentString(savedDir,dir)
 ||  savedSubDir == NULL || differentString(savedSubDir,subDir))
     {
     // free up any static mem
     freeMem(savedDb);
     freeMem(savedDir);
     freeMem(savedSubDir);
     fileDbFree(&foundFiles);
 
 #ifdef CACHE_IS_FASTER_THAN_RSYNC
-    if (fileDbCacheAvailable(db, dir, subDir))  // check cache first
-        {
-        foundFiles = fileDbReadFromCache(db, dir, subDir);
-        }
+    if (fileDbBackupAvailable(db, dir, subDir))  // check backup first
+        foundFiles = fileDbReadFromBackup(db, dir, subDir);
     else
 #endif///def CACHE_IS_FASTER_THAN_RSYNC
         {
         FILE *scriptOutput = NULL;
         char buf[1024];
         char cmd[512];
         char *words[10];
         char *server = hDownloadsServer();
 
         boolean useRsync = TRUE;
         // Works:         rsync -avn rsync://hgdownload.cse.ucsc.edu/goldenPath/hg18/encodeDCC/wgEncodeBroadChipSeq/
         if (hIsBetaHost())
             safef(cmd,sizeof(cmd),"rsync -n rsync://hgdownload-test.cse.ucsc.edu/goldenPath/%s/%s/%s/beta/",  db, dir, subDir); // NOTE: Force this case because beta may think it's downloads server is "hgdownload.cse.ucsc.edu"
         else
             safef(cmd,sizeof(cmd),"rsync -n rsync://%s/goldenPath/%s/%s/%s/", server, db, dir, subDir);
@@ -174,42 +163,42 @@
                     {
                     //-rw-rw-r--    26420982 2009/09/29 14:53:30 wgEncodeBroadChipSeq/wgEncodeBroadChipSeqSignalNhlfH4k20me1.wig.gz
                     AllocVar(oneFile);
                     oneFile->fileSize = sqlUnsignedLong(words[1]);
                     oneFile->fileDate = cloneString(words[2]);
                     strSwapChar(oneFile->fileDate,'/','-');// Standardize YYYY-MM-DD, no time
                     oneFile->fileName = cloneString(words[4]);
                     slAddHead(&foundFiles,oneFile);
                     }
                 //warn("File:%s  size:%ld",foundFiles->fileName,foundFiles->fileSize);
                 }
             }
         pclose(scriptOutput);
         if (foundFiles == NULL)
             {
-            foundFiles = fileDbReadFromCache(db, dir, subDir);
+            foundFiles = fileDbReadFromBackup(db, dir, subDir);
             if (foundFiles == NULL)
                 {
                 AllocVar(oneFile);
                 oneFile->fileName = cloneString("No files found!");
                 oneFile->fileDate = cloneString(cmd);
                 slAddHead(&foundFiles,oneFile);
                 warn("No files found for command:\n%s",cmd);
                 }
             }
         else
-            fileDbWriteToCache(db, dir, subDir,foundFiles);
+            fileDbWriteToBackup(db, dir, subDir,foundFiles);
         }
 
     // mark this as done to avoid excessive io
     savedDb     = cloneString(db);
     savedDir    = cloneString(dir);
     savedSubDir = cloneString(subDir);
 
     if (foundFiles == NULL)
         return NULL;
     }
 
 // special code that only gets called in debug mode
 if (sameString(fileName,"listAll"))
     {
     for(oneFile=foundFiles;oneFile;oneFile=oneFile->next)
@@ -478,30 +467,37 @@
         {
         char *var = sortOrder->column[sIx];
         enum cvSearchable searchBy = cvSearchMethod(var);
     //#define FILTERBY_ALL_SEARCHABLE
     #ifdef FILTERBY_ALL_SEARCHABLE
         if (searchBy == cvNotSearchable)
     #else///ifndef FILTERBY_ALL_SEARCHABLE
         if (searchBy == cvNotSearchable || searchBy == cvSearchByFreeText)
     #endif///ndef FILTERBY_ALL_SEARCHABLE
             continue; // Only single selects and multi-select make good candidates for filtering
 
         // get all vals for var, then convert to tag/label pairs for filterBys
         struct slName *vals = mdbObjsFindAllVals(mdbObjs, var, CV_LABEL_EMPTY_IS_NONE);
         if (searchBy != cvSearchByMultiSelect && searchBy != cvSearchBySingleSelect)
             {
+            // We can't be too ambitious about creating filterboxes on the fly so some limitations:
+            // If there are more than 80 options, the filterBy is way too large and of limited use
+            // If there is a distinct val for each file in the table, then the filterBy is the same size
+            //    as the table and of no help.  Really the number of options should be half the number of rows
+            //    but we are being lenient and cutting off at 0.8 not 0.5
+            // If there is any non-alphanum char in a value then the filterBy will fail in js code.
+            //    Those filterBy's are abandoned a but further down.
             int valCount = slCount(vals);
             if (valCount > 80 || valCount > (slCount(mdbObjs) * 0.8))
                 {
                 slNameFreeList(&vals);
                 continue;
                 }
             }
         struct slPair *tagLabelPairs = NULL;
         while(vals != NULL)
             {
             char buf[256];
             struct slName *term = slPopHead(&vals);
             char *tag = (char *)cvTag(var,term->name);
             if (tag == NULL)                           // Does not require cv defined!
                 {
@@ -535,32 +531,32 @@
                 slPairValSortCase(&tagLabelPairs);
             char extraClasses[256];
             safef(extraClasses,sizeof extraClasses,"filterTable %s",var);
         #ifdef NEW_JQUERY
             char *dropDownHtml = cgiMakeMultiSelectDropList(var,tagLabelPairs,NULL,"All",extraClasses,"onchange='filterTable(this);' style='font-size:.9em;'");
         #else///ifndef NEW_JQUERY
             char *dropDownHtml = cgiMakeMultiSelectDropList(var,tagLabelPairs,NULL,"All",extraClasses,"onchange='filterTable();' onclick='filterTableExclude(this);'");
         #endif///ndef NEW_JQUERY
             // Note filterBox has classes: filterBy & {var}
             if (dropDownHtml)
                 {
                 dyStringPrintf(dyFilters,"<td align='left'>\n<B>%s</B>:<BR>\n%s</td><td width=10>&nbsp;</td>\n",
                                labelWithVocabLink(var,sortOrder->title[sIx],tagLabelPairs,TRUE),dropDownHtml);  // TRUE were sending tags, not values
                 freeMem(dropDownHtml);
                 count++;
+                if (sIx < 64) // avoid bit overflow but 64 filterBoxes?  I don't think so
                 filterableBits |= (0x1<<(sIx));
-                //warn("count:%d sIx:%d retBits:%X",count,sIx,filterableBits);
                 }
             }
         if (tagLabelPairs != NULL)
             slPairFreeValsAndList(&tagLabelPairs);
         }
 
     // Finally ready to print the filterBys out
     if (count)
         {
         webIncludeResourceFile("ui.dropdownchecklist.css");
         jsIncludeFile("ui.dropdownchecklist.js",NULL);
         #define FILTERBY_HELP_LINK  "<A HREF=\"../goldenPath/help/multiView.html\" TARGET=ucscHelp>help</A>"
         cgiDown(0.9);
         printf("<B>Filter files by:</B> (select multiple %sitems - %s)\n<table><tr valign='bottom'>\n",
                (count >= 1 ? "categories and ":""),FILTERBY_HELP_LINK);