8fdc86ea29f656cf7efee9954fdae6b573190fb3 tdreszer Fri May 6 17:23:22 2011 -0700 Standardized replacement for
with cgiDown and worked out more spacing issues in hgFileUi and hgTrackUi.
diff --git src/hg/lib/fileUi.c src/hg/lib/fileUi.c
index eefb10d..eaf276f 100644
--- src/hg/lib/fileUi.c
+++ src/hg/lib/fileUi.c
@@ -1,988 +1,989 @@
/* fileUi.c - human genome file downloads common controls. */
#include "common.h"
#include "hash.h"
#include "cheapcgi.h"
#include "jsHelper.h"
#include "cart.h"
#include "hdb.h"
#include "fileUi.h"
#include "hui.h"
#include "obscure.h"
#include "mdb.h"
#include "jsHelper.h"
#include "web.h"
// FIXME: Move to hui.h since hui.c also needs this
#define ENCODE_DCC_DOWNLOADS "encodeDCC"
void fileDbFree(struct fileDb **pFileList)
// free one or more fileDb objects
{
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);
}
}
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.
{
static char *savedDb = NULL;
static char *savedDir = NULL;
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);
FILE *scriptOutput = NULL;
char buf[1024];
char cmd[512];
char *words[10];
char *server = hDownloadsServer();
boolean useRsync = TRUE;
//#define RSYNC_DONT_WORK_ON_HGWDEV
#ifdef RSYNC_DONT_WORK_ON_HGWDEV
if (hIsPrivateHost() || hIsPreviewHost())
{
// For hgwdev (which is the same machine as "hgdownload-test.cse.ucsc.edu") rsync does not work
// Use ls -log --time=ctime --time-style=long-iso /usr/local/apache/htdocs-hgdownload/goldenPath/hg19/encodeDCC/wgEncodeBroadHistone
safef(cmd,sizeof(cmd),"ls -log --time-style=long-iso /usr/local/apache/htdocs-hgdownload/goldenPath/%s/%s/%s/", db,dir,subDir);
useRsync = FALSE;
}
else if (hIsBetaHost())
{
// For hgwbeta, the files are being looked for one test in a "beta/" subdir. Have to rsync
//server = "hgdownload-test.cse.ucsc.edu"; // NOTE: Force this case because beta may think it's downloads server is "hgdownload.cse.ucsc.edu"
//safef(cmd,sizeof(cmd),"rsync -avn rsync://%s/goldenPath/%s/%s/%s/beta/", server, db, dir, subDir);
// FIXME: Need cluster-admins help to get rsync solution
safef(cmd,sizeof(cmd),"ls -log --time-style=long-iso /hive/groups/encode/dcc/pipeline/downloads/%s/%s/beta/", db,subDir);
useRsync = FALSE;
}
else // genome and hgwbeta can use rsync
#endif///def RSYNC_DONT_WORK_ON_HGWDEV
{
// Works: rsync -avn rsync://hgdownload.cse.ucsc.edu/goldenPath/hg18/encodeDCC/wgEncodeBroadChipSeq/
if (hIsBetaHost())
safef(cmd,sizeof(cmd),"rsync -avn 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 -avn rsync://%s/goldenPath/%s/%s/%s/", server, db, dir, subDir);
}
//warn("cmd: %s",cmd);
scriptOutput = popen(cmd, "r");
while(fgets(buf, sizeof(buf), scriptOutput))
{
eraseTrailingSpaces(buf);
if (!endsWith(buf,".md5sum")) // Just ignore these
{
int count = chopLine(buf, words);
if (count >= 6 && useRsync == FALSE) // hgwdev is same as hgdownloads-test so can't use rsync
{
//-rw-rw-r-- 5 502826550 2010-10-22 16:51 /usr/local/apache/htdocs-hgdownload/goldenPath/hg19/encodeDCC/wgEncodeBroadHistone/wgEncodeBroadHistoneGm12878ControlStdRawDataRep1.fastq.gz
AllocVar(oneFile);
oneFile->fileSize = sqlUnsignedLong(words[2]);
oneFile->fileDate = cloneString(words[3]);
char *atSlash = strrchr(words[5], '/');
if (atSlash != NULL)
oneFile->fileName = cloneString(atSlash + 1);
else
oneFile->fileName = cloneString(words[5]);
slAddHead(&foundFiles,oneFile);
}
else if (count == 5 && useRsync == TRUE)// genome and hgwbeta can use rsync because files are on different machine
{
//-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);
// mark this as done to avoid excessive io
savedDb = cloneString(db);
savedDir = cloneString(dir);
savedSubDir = cloneString(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);
return NULL;
}
}
// special code that only gets called in debug mode
if (sameString(fileName,"listAll"))
{
for(oneFile=foundFiles;oneFile;oneFile=oneFile->next)
warn("%s",oneFile->fileName);
return NULL;
}
// Look up the file and return it
struct fileDb *newList = NULL;
while (foundFiles)
{
oneFile = slPopHead(&foundFiles);
if (sameString(fileName,oneFile->fileName))
break; // Found means removed from list: shorter list for next file.
slAddHead(&newList,oneFile);
oneFile = NULL;
}
if (newList)
foundFiles = slCat(foundFiles,newList); // Order does not remain the same
if (oneFile != NULL && oneFile->fileType == NULL)
{
char *suffix = strchr(oneFile->fileName, '.');
if (suffix != NULL && strlen(suffix) > 2)
{
oneFile->fileType = cloneString(suffix + 1);
if (endsWith(oneFile->fileType,".gz"))
chopSuffix(oneFile->fileType);
}
}
return oneFile;
}
static sortOrder_t *fileSortOrderGet(struct cart *cart,struct trackDb *parentTdb,struct mdbObj *mdbObjs)
/* Parses 'fileSortOrder' trackDb/cart instructions and returns a sort order struct or NULL.
Some trickiness here. sortOrder->sortOrder is from cart (changed by user action), as is sortOrder->order,
But columns are in original tdb order (unchanging)! However, if cart is null, all is from trackDb.ra */
{
int ix;
sortOrder_t *sortOrder = NULL;
char *carveSetting = NULL,*setting = NULL;
if (parentTdb)
setting = trackDbSetting(parentTdb, FILE_SORT_ORDER);
if(setting)
{
sortOrder = needMem(sizeof(sortOrder_t));
sortOrder->setting = cloneString(setting);
carveSetting = sortOrder->setting;
}
else
{
if (mdbObjs != NULL)
{
struct dyString *dySortFields = dyStringNew(512);
struct mdbObj *commonVars = mdbObjsCommonVars(mdbObjs);
// common vars are already in cv defined order, searchable is also sortable
struct mdbVar *var = commonVars->vars;
for( ;var != NULL; var = var->next)
{
if (differentWord(var->var,MDB_VAR_LAB_VERSION) // Exclude certain vars
&& differentWord(var->var,MDB_VAR_SOFTWARE_VERSION)
&& cvSearchMethod(var->var) != cvNotSearchable) // searchable is also sortable
{
if (mdbObjsHasCommonVar(mdbObjs, var->var,TRUE)) // Don't bother if all the vals are the same (missing okay)
continue;
dyStringPrintf(dySortFields,"%s=%s ",var->var,strSwapChar(cloneString(cvLabel(var->var)),' ','_'));
}
}
if (dyStringLen(dySortFields))
{
dyStringAppend(dySortFields,"fileSize=Size fileType=File_Type");
setting = dyStringCannibalize(&dySortFields);
}
else
dyStringFree(&dySortFields);
mdbObjsFree(&commonVars);
}
if(setting == NULL) // Must be in trackDb or not a sortable list of files
{
#define FILE_SORT_ORDER_DEFAULT "cell=Cell_Line lab=Lab view=View replicate=Rep fileSize=Size fileType=File_Type dateSubmitted=Submitted dateUnrestricted=RESTRICTED Data is RESTRICTED FROM USE");
-puts("in publication until the restriction date noted for the given data file. \nSupplemental materials may be found here. \nThere are two files within this directory that contain information about the downloads:");
+cgiDown(0.7);
+puts("There are two files within this directory that contain information about the downloads:");
printf(" ");
}
static int filesPrintTable(char *db, struct trackDb *parentTdb, struct fileDb *fileList, sortOrder_t *sortOrder,boolean filterable)
// Prints filesList as a sortable table. Returns count
{
// Table class=sortable
int columnCount = 0;
int restrictedColumn = 0;
char *nowrap = (sortOrder->setting != NULL ? " nowrap":""); // Sort order trackDb setting found so rely on
Until"
setting = FILE_SORT_ORDER_DEFAULT;
}
sortOrder = needMem(sizeof(sortOrder_t));
carveSetting = cloneString(setting);
sortOrder->setting = NULL;
}
if (parentTdb)
{
sortOrder->htmlId = needMem(strlen(parentTdb->track)+20);
safef(sortOrder->htmlId, (strlen(parentTdb->track)+20), "%s.%s", parentTdb->track,FILE_SORT_ORDER);
if(cart != NULL)
sortOrder->sortOrder = cloneString(cartOptionalString(cart, sortOrder->htmlId));
}
sortOrder->count = chopByWhite(carveSetting,NULL,0); // Get size
sortOrder->column = needMem(sortOrder->count*sizeof(char*));
sortOrder->count = chopByWhite(carveSetting,sortOrder->column,sortOrder->count);
sortOrder->title = needMem(sortOrder->count*sizeof(char*));
sortOrder->forward = needMem(sortOrder->count*sizeof(boolean));
sortOrder->order = needMem(sortOrder->count*sizeof(int));
for (ix = 0; ix\n%s:
\n%s \n",
labelWithVocabLink(var,sortOrder->title[sIx],relevantVals,TRUE),dropDownHtml); // TRUE were sending tags, not values
freeMem(dropDownHtml);
count++;
}
}
if (slCount(relevantVals) > 0)
slPairFreeValsAndList(&relevantVals);
}
if (count)
{
webIncludeResourceFile("ui.dropdownchecklist.css");
jsIncludeFile("ui.dropdownchecklist.js",NULL);
#define FILTERBY_HELP_LINK "help"
+ cgiDown(0.9);
printf("Filter files by: (select multiple %sitems - %s)\n
\n");
printf("\n");
}
dyStringFree(&dyFilters);
}
return count;
}
static void filesDownloadsPreamble(char *db, struct trackDb *tdb)
{
// Do not bother getting preamble.html
// 1) It isn't on the RR (yet)
// 2) It will likely refer back to the composite for Description info which is included in this page
// 3) The rsync-to-tmp-file hurdle isn't worth the effort.
-puts("\n",
(count >= 1 ? "categories and ":""),FILTERBY_HELP_LINK);
printf("%s\n",dyStringContents(dyFilters));
printf("
files.txt which is a tab-separated file with the name and metadata for each download.\n",
server,db,ENCODE_DCC_DOWNLOADS, tdb->track, subDir);
printf("
md5sum.txt which is a list of the md5sum output for each download.\n",
server,db,ENCODE_DCC_DOWNLOADS, tdb->track, subDir);
-
-
-puts("
in titles for wrapping
printf("\n");
printf("\n");
printf("
\n");
printf(" \n");
// Now the files...
char *server = hDownloadsServer();
char *subDir = "";
if (hIsBetaHost())
{
server = "hgdownload-test.cse.ucsc.edu"; // NOTE: Force this case because beta may think it's downloads server is "hgdownload.cse.ucsc.edu"
subDir = "/beta";
}
struct fileDb *oneFile = fileList;
printf("\n"); // 'sorting' is a fib but it conveniently greys the list till the table is initialized.
for( ;oneFile!= NULL;oneFile=oneFile->next)
{
oneFile->mdb->next = NULL; // mdbs were in list for generating sortOrder, but list no longer needed
char *field = NULL;
printf(" ");
int filesCount = slCount(fileList);
if (filesCount > 5)
printf("%d files",filesCount);
//if (sortOrder) // NOTE: This could be done to preserve sort order FIXME: However hgFileUi would need form OR changes would need to be ajaxed over AND hgsid would be needed.
// printf("",sortOrder->htmlId, sortOrder->sortOrder);
printf(" \n");
columnCount++;
/*#define SHOW_FOLDER_FRO_COMPOSITE_DOWNLOADS
#ifdef SHOW_FOLDER_FRO_COMPOSITE_DOWNLOADS
if (parentTdb == NULL)
{
printf(" ");
columnCount++;
}
#endif///def SHOW_FOLDER_FRO_COMPOSITE_DOWNLOADS
*/
// Now the columns
int curOrder = 0,ix=0;
if (sortOrder)
{
curOrder = sortOrder->count;
for(ix=0;ix%s \n",
sortOrder->order[ix],(sortOrder->forward[ix]?"":" sortRev"),
(sameString("fileSize",sortOrder->column[ix])?"abbr='use' ":""),
nowrap,align,sortOrder->title[ix]); // keeing track of sortOrder
columnCount++;
if (sameWord(sortOrder->column[ix],"dateUnrestricted"))
restrictedColumn = columnCount;
}
}
//#define INCLUDE_FILENAMES
#ifndef INCLUDE_FILENAMES
else
#endif///defn INCLUDE_FILENAMES
{
printf("File Name \n",++curOrder);
columnCount++;
}
printf("Additional Details \n",++curOrder);
columnCount++;
printf("",filterable?" class='filterable'":"");
// Download button
printf(" \n");
}
printf("\n");
printf("");
if (parentTdb)
field = parentTdb->track;
else
field = mdbObjFindValue(oneFile->mdb,"composite");
assert(field != NULL);
printf("",
server,db,ENCODE_DCC_DOWNLOADS, field, subDir, oneFile->fileName, oneFile->fileName);
#define SHOW_FOLDER_FRO_COMPOSITE_DOWNLOADS
#ifdef SHOW_FOLDER_FRO_COMPOSITE_DOWNLOADS
if (parentTdb == NULL)
printf(" \n");
// Each of the pulled out mdb vars
if (sortOrder)
{
for(ix=0;ix ", db,field,field);
#endif///def SHOW_FOLDER_FRO_COMPOSITE_DOWNLOADS
printf("
%s ",field,niceNumber);
}
else
{
field = oneFile->sortFields[sortOrder->order[ix] - 1];
char class[128];
class[0] = '\0';
if (filterable)
{
enum cvSearchable searchBy = cvSearchMethod(sortOrder->column[ix]);
if (searchBy == cvSearchBySingleSelect || searchBy == cvSearchByMultiSelect)
{
char *cleanClass = cloneString(field?field:"None"); // FIXME: Only none if none is a fliter choice.
eraseNonAlphaNum(cleanClass);
safef(class,sizeof class," class='%s %s'",sortOrder->column[ix],cleanClass);
}
}
if (sameString("dateUnrestricted",sortOrder->column[ix]) && field && dateIsOld(field,"%F"))
printf("%s ",align,class,field);
else
printf("%s ",align,class,field?field:" ");
if (!sameString("fileType",sortOrder->column[ix]))
mdbObjRemoveVars(oneFile->mdb,sortOrder->column[ix]); // Remove this from mdb now so that it isn't displayed in "extras'
}
}
}
#ifndef INCLUDE_FILENAMES
else
#endif///ndef INCLUDE_FILENAMES
{ // fileName
printf("%s",oneFile->fileName);
//// FIXME: " The "..." encapsulation could be rebuilt so it could be called here
//printf(" ...",
// oneFile->mdb->obj,oneFile->mdb->obj);
//printf(" ",oneFile->mdb->obj);
}
// Extras grant=Bernstein; lab=Broad; dataType=ChipSeq; setType=exp; control=std;
mdbObjRemoveVars(oneFile->mdb,MDB_VAR_FILENAME " " MDB_VAR_FILEINDEX " " MDB_VAR_COMPOSITE " " MDB_VAR_PROJECT); // Remove this from mdb now so that it isn't displayed in "extras'
field = mdbObjVarValPairsAsLine(oneFile->mdb,TRUE);
printf("%s ",field?field:" ");
printf("");
// Restriction policy link in first column?
if (restrictedColumn == 1)
printf(" \n");
-printf("Restriction Policy ", (columnCount - restrictedColumn),ENCODE_DATA_RELEASE_POLICY);
printf(" ",(restrictedColumn > 1 ? (restrictedColumn - 1) : columnCount));
// Total
if (filesCount > 5)
printf("%d files",filesCount);
// Restriction policy link in later column?
if (restrictedColumn > 1)
printf(" Restriction Policy", columnCount,ENCODE_DATA_RELEASE_POLICY);
printf("
\n");
+printf("\n");
if (parentTdb == NULL)
printf("\n");
return filesCount;
}
static int filesFindInDir(char *db, struct mdbObj **pmdbFiles, struct fileDb **pFileList, char *fileType, int limit,boolean *exceededLimit)
// Prints list of files in downloads directories matching mdb search terms. Returns count
{
int fileCount = 0;
// Verify file existance and make fileList of those found
struct fileDb *fileList = NULL, *oneFile = NULL; // Will contain found files
struct mdbObj *mdbFiles = NULL; // Will caontain a list of mdbs for the found files
struct mdbObj *mdbList = *pmdbFiles;
while (mdbList && (limit == 0 || fileCount < limit))
{
boolean found = FALSE;
struct mdbObj *mdbFile = slPopHead(&mdbList);
char *composite = mdbObjFindValue(mdbFile,MDB_VAR_COMPOSITE);
if (composite == NULL)
{
mdbObjsFree(&mdbFile);
continue;
}
// First for FileName
char *fileName = mdbObjFindValue(mdbFile,MDB_VAR_FILENAME);
if (fileName == NULL)
{
mdbObjsFree(&mdbFile);
continue;
}
//#define NO_FILENAME_LISTS
#ifdef NO_FILENAME_LISTS
oneFile = fileDbGet(db, ENCODE_DCC_DOWNLOADS, composite, fileName);
if (oneFile == NULL)
{
mdbObjsFree(&mdbFile);
continue;
}
//warn("%s == %s",fileType,oneFile->fileType);
if (isEmpty(fileType) || sameWord(fileType,"Any")
|| (oneFile->fileType && sameWord(fileType,oneFile->fileType)))
{
slAddHead(&fileList,oneFile);
oneFile->mdb = mdbFile;
slAddHead(&mdbFiles,oneFile->mdb);
found = TRUE;
fileCount++;
if (limit > 0 && fileCount >= limit)
break;
}
else
fileDbFree(&oneFile);
#else///ifndef NO_FILENAME_LISTS
struct slName *fileSet = slNameListFromComma(fileName);
struct slName *md5Set = NULL;
char *md5sums = mdbObjFindValue(mdbFile,MDB_VAR_MD5SUM);
if (md5sums != NULL)
md5Set = slNameListFromComma(md5sums);
while (fileSet != NULL)
{
struct slName *file = slPopHead(&fileSet);
struct slName *md5 = NULL;
if (md5Set)
md5 = slPopHead(&md5Set);
oneFile = fileDbGet(db, ENCODE_DCC_DOWNLOADS, composite, file->name);
if (oneFile == NULL)
{
slNameFree(&file);
if (md5)
slNameFree(&md5);
continue;
}
//warn("%s == %s",fileType,oneFile->fileType);
if (isEmpty(fileType) || sameWord(fileType,"Any")
|| (oneFile->fileType && startsWithWordByDelimiter(fileType,'.',oneFile->fileType))) // Starts with! This ensures both bam and bam.bai are found.
{
slAddHead(&fileList,oneFile);
if (found) // if already found then need two mdbObjs (assertable but then this is metadata)
oneFile->mdb = mdbObjClone(mdbFile); // Yes clone this as differences will occur
else
oneFile->mdb = mdbFile;
if (md5 != NULL)
mdbObjSetVar(oneFile->mdb,MDB_VAR_MD5SUM,md5->name);
else
mdbObjRemoveVars(oneFile->mdb,MDB_VAR_MD5SUM);
slAddHead(&mdbFiles,oneFile->mdb);
found = TRUE;
fileCount++;
if (limit > 0 && fileCount >= limit)
{
slNameFreeList(&fileSet);
if (md5Set)
slNameFreeList(&md5Set);
break;
}
}
else
fileDbFree(&oneFile);
slNameFree(&file);
if (md5)
slNameFree(&md5);
}
#endif///ndef NO_FILENAME_LISTS
// FIXME: This support of fileIndex and implicit bam.bai's should be removed when mdb is cleaned up.
// Now for FileIndexes
if (limit == 0 || fileCount < limit)
{
char buf[512];
if (strchr(fileName,',') == NULL && endsWith(fileName,".bam")) // Special to fill in missing .bam.bai's
{
safef(buf,sizeof(buf),"%s.bai",fileName);
fileName = buf;
}
else
{
fileName = mdbObjFindValue(mdbFile,MDB_VAR_FILEINDEX); // This mdb var should be going away.
if (fileName == NULL)
continue;
}
// Verify existance first
oneFile = fileDbGet(db, ENCODE_DCC_DOWNLOADS, composite, fileName); // NOTE: won't be found if already found in comma delimited fileName!
if (oneFile == NULL)
continue;
//warn("%s == %s",fileType,oneFile->fileType);
if (isEmpty(fileType) || sameWord(fileType,"Any")
|| (oneFile->fileType && sameWord(fileType,oneFile->fileType))
|| (oneFile->fileType && sameWord(fileType,"bam") && sameWord("bam.bai",oneFile->fileType))) // TODO: put fileType matching into search.c lib code to segregate index logic.
{
slAddHead(&fileList,oneFile);
if (found) // if already found then need two mdbObjs (assertable but then this is metadata)
oneFile->mdb = mdbObjClone(mdbFile);
else
oneFile->mdb = mdbFile;
mdbObjRemoveVars(oneFile->mdb,MDB_VAR_MD5SUM);
slAddHead(&mdbFiles,oneFile->mdb);
fileCount++;
found = TRUE;
continue;
}
else
fileDbFree(&oneFile);
}
if (!found)
mdbObjsFree(&mdbFile);
}
*pmdbFiles = mdbFiles;
*pFileList = fileList;
if (exceededLimit != NULL)
*exceededLimit = FALSE;
if (mdbList != NULL)
{
if (exceededLimit != NULL)
*exceededLimit = TRUE;
mdbObjsFree(&mdbList);
}
return fileCount;
}
void filesDownloadUi(char *db, struct cart *cart, struct trackDb *tdb)
// UI for a "composite like" track: This will list downloadable files associated with
// a single trackDb entry (composite or of type "downloadsOnly". The list of files
// will have links to their download and have metadata information associated.
// The list will be a sortable table and there may be filtering controls.
{
boolean debug = cartUsualBoolean(cart,"debug",FALSE);
struct sqlConnection *conn = hAllocConn(db);
char *mdbTable = mdbTableName(conn,TRUE); // Look for sandBox name first
if(mdbTable == NULL)
errAbort("TABLE NOT FOUND: '%s.%s'.\n",db,MDB_DEFAULT_NAME);
// Get an mdbObj list of all that belong to this track and have a fileName
char buf[256];
safef(buf,sizeof(buf),"%s=%s %s=?",MDB_VAR_COMPOSITE,tdb->track,MDB_VAR_FILENAME);
struct mdbByVar *mdbVars = mdbByVarsLineParse(buf);
struct mdbObj *mdbList = mdbObjsQueryByVars(conn,mdbTable,mdbVars);
// Now get Indexes But be sure not to duplicate entries in the list!!!
safef(buf,sizeof(buf),"%s=%s %s= %s!=",MDB_VAR_COMPOSITE,tdb->track,MDB_VAR_FILEINDEX,MDB_VAR_FILENAME);
mdbVars = mdbByVarsLineParse(buf);
mdbList = slCat(mdbList, mdbObjsQueryByVars(conn,mdbTable,mdbVars));
mdbObjRemoveHiddenVars(mdbList);
hFreeConn(&conn);
if (slCount(mdbList) == 0)
{
warn("No files specified in metadata for: %s\n%s",tdb->track,tdb->longLabel);
return;
}
// Verify file existance and make fileList of those found
struct fileDb *fileList = NULL; // Will contain found files
int fileCount = filesFindInDir(db, &mdbList, &fileList, NULL, 0, NULL);
assert(fileCount == slCount(fileList));
if (fileCount == 0)
{
warn("No downloadable files currently available for: %s\n%s",tdb->track,tdb->longLabel);
return; // No files so nothing to do.
}
if (debug)
{
warn("The following files are in goldenPath/%s/%s/%s/ but NOT in the mdb:",db,ENCODE_DCC_DOWNLOADS, tdb->track);
fileDbGet(db, ENCODE_DCC_DOWNLOADS, tdb->track, "listAll");
}
jsIncludeFile("hui.js",NULL);
jsIncludeFile("ajax.js",NULL);
// standard preamble
filesDownloadsPreamble(db,tdb);
// Now update all files with their sortable fields and sort the list
mdbObjReorderByCv(mdbList,FALSE);// Start with cv defined order for visible vars. NOTE: will not need to reorder during print!
sortOrder_t *sortOrder = fileSortOrderGet(cart,tdb,mdbList);
boolean filterable = FALSE;
if (sortOrder != NULL)
{
char *vars = removeCommonMdbVarsNotInSortOrder(mdbList,sortOrder);
if (vars)
{
if (debug)
warn("These terms are common:%s",vars);
freeMem(vars);
}
// Fill in and sort fileList
fileDbSortList(&fileList,sortOrder);
// FilterBoxes
filterable = (filterBoxesForFilesList(db,mdbList,sortOrder) > 0);
}
// Print table
filesPrintTable(db,tdb,fileList,sortOrder,filterable);
//fileDbFree(&fileList); // Why bother on this very long running cgi?
//mdbObjsFree(&mdbList);
}
int fileSearchResults(char *db, struct sqlConnection *conn, struct slPair *varValPairs, char *fileType)
// Prints list of files in downloads directories matching mdb search terms. Returns count
{
struct sqlConnection *connLocal = conn;
if (conn == NULL)
connLocal = hAllocConn(db);
struct mdbObj *mdbList = mdbObjRepeatedSearch(connLocal,varValPairs,FALSE,TRUE);
if (conn == NULL)
hFreeConn(&connLocal);
if (slCount(mdbList) == 0)
{
printf("
No files found.
\n");
return 0;
}
// Now sort mdbObjs so that composites will stay together and lookup of files will be most efficient
mdbObjsSortOnVars(&mdbList, MDB_VAR_COMPOSITE);
mdbObjRemoveHiddenVars(mdbList);
#define FOUND_FILE_LIMIT 1000
struct fileDb *fileList = NULL; // Will contain found files
int filesExpected = slCount(mdbList);
boolean exceededLimit = FALSE;
int fileCount = filesFindInDir(db, &mdbList, &fileList, fileType, FOUND_FILE_LIMIT, &exceededLimit);
assert(fileCount == slCount(fileList));
if (fileCount == 0)
{
printf("
No files found.
\n");
return 0; // No files so nothing to do.
}
// TODO Could sort on varValPairs by creating a sortOrder struct of them
//// Now update all files with their sortable fields and sort the list
mdbObjReorderByCv(mdbList,FALSE);// Start with cv defined order for visible vars. NOTE: will not need to reorder during print!
sortOrder_t *sortOrder = fileSortOrderGet(NULL,NULL,mdbList); // No cart, no tdb
if (sortOrder != NULL)
{
// Fill in and sort fileList
fileDbSortList(&fileList,sortOrder);
}
mdbObjRemoveVars(mdbList,"tableName"); // Remove this from mdb now so that it isn't displayed in "extras'
//jsIncludeFile("hui.js",NULL);
//jsIncludeFile("ajax.js",NULL);
// Print table
printf("
Narrow search parameters and try again.
\n",
fileCount,filesExpected);
//warn("Too many files found. Displaying first %d of at least %d.
Narrow search parameters and try again.\n", fileCount,filesExpected);
}
fileCount = filesPrintTable(db,NULL,fileList,sortOrder,FALSE); // FALSE=Don't offer more filtering on the file search page
printf("
\n");
//fileDbFree(&fileList); // Why bother on this very long running cgi?
//mdbObjsFree(&mdbList);
return fileCount;
}