9e3bb75e688ebfde51e193061f2f0946400f3116
braney
  Thu Dec 20 16:02:42 2012 -0800
clean up error handling a little in support of #3130.   Made failure to open seq file equivalent to other errors finding sequence in the database.  This should change nothing if the seq is found, and should only change the error message if the file mentioned in extFile is not found, in which case the error will be something like "can't find sequence blatDeBlah" instead of "External file /gbdb/genbank/./data/processed/refseq.46/full/mrna.fa cannot be opened or has wrong size." Codon and base translation in hgTracks will fail silently and default to the standard display if the sequence is not available.
diff --git src/hg/lib/hdb.c src/hg/lib/hdb.c
index 40e337d..9ad7978 100644
--- src/hg/lib/hdb.c
+++ src/hg/lib/hdb.c
@@ -1208,64 +1208,83 @@
 struct sqlConnection *conn = hAllocConn(db);
 struct sqlResult *sr;
 char **row;
 
 sr = sqlGetResult(conn, "select chrom from chromInfo");
 while ((row = sqlNextRow(sr)) != NULL)
     {
     struct slName *el = slNameNew(row[0]);
     slAddHead(&list, el);
     }
 sqlFreeResult(&sr);
 hFreeConn(&conn);
 return list;
 }
 
-char *hExtFileNameC(struct sqlConnection *conn, char *extFileTable, unsigned extFileId)
+char *hTryExtFileNameC(struct sqlConnection *conn, char *extFileTable, unsigned extFileId, boolean abortOnError)
 /* Get external file name from table and ID.  Typically
  * extFile table will be 'extFile' or 'gbExtFile'
  * Abort if the id is not in the table or if the file
  * fails size check.  Please freeMem the result when you
- * are done with it. (requires conn passed in) */
+ * are done with it. (requires conn passed in) 
+ * If abortOnError is true, will abort, otherwise returns NULL
+ */
 {
 char query[256];
 struct sqlResult *sr;
 char **row;
 long long dbSize, diskSize;
 char *path;
 
 safef(query, sizeof(query),
 	"select path,size from %s where id = %u", extFileTable, extFileId);
 sr = sqlGetResult(conn, query);
 if ((row = sqlNextRow(sr)) == NULL)
     {
+    if (abortOnError)
     errAbort("Database inconsistency table '%s.%s' no ext file with id %u",
              sqlGetDatabase(conn), extFileTable, extFileId);
+    else 
+	return NULL;
     }
+
 path = cloneString(row[0]);
 dbSize = sqlLongLong(row[1]);
 diskSize = fileSize(path);
+sqlFreeResult(&sr);
+
 if (dbSize != diskSize)
     {
+    if (abortOnError)
     errAbort("External file %s cannot be opened or has wrong size.  "
              "Old size %lld, new size %lld, error %s",
              path, dbSize, diskSize, strerror(errno));
+    else 
+	freez(&path);
     }
-sqlFreeResult(&sr);
 return path;
 }
 
+char *hMayExtFileNameC(struct sqlConnection *conn, char *extFileTable, unsigned extFileId)
+{
+return hTryExtFileNameC(conn, extFileTable, extFileId, FALSE);
+}
+
+char *hExtFileNameC(struct sqlConnection *conn, char *extFileTable, unsigned extFileId)
+{
+return hTryExtFileNameC(conn, extFileTable, extFileId, TRUE);
+}
 
 char *hExtFileName(char *db, char *extFileTable, unsigned extFileId)
 /* Get external file name from table and ID.  Typically
  * extFile table will be 'extFile' or 'gbExtFile'
  * Abort if the id is not in the table or if the file
  * fails size check.  Please freeMem the result when you
  * are done with it. */
 {
 struct sqlConnection *conn = hAllocConn(db);
 char *path=hExtFileNameC(conn,extFileTable,extFileId);
 hFreeConn(&conn);
 return path;
 }
 
 
@@ -1295,33 +1314,38 @@
 static struct largeSeqFile *largeFileHandle(struct sqlConnection *conn, HGID extId, char *extTable)
 /* Return handle to large external file. */
 {
 struct largeSeqFile *lsf;
 char *db = sqlGetDatabase(conn);
 
 /* Search for it on existing list and return it if found. */
 for (lsf = largeFileList; lsf != NULL; lsf = lsf->next)
     {
     if ((lsf->id == extId) && sameString(lsf->db, db) && sameString(lsf->extTable, extTable))
         return lsf;
     }
 
 /* Open file and put it on list. */
     {
+    char *path;
+    path = hMayExtFileNameC(conn, extTable, extId);
+    if (path == NULL)
+	return NULL;
+
     struct largeSeqFile *lsf;
     AllocVar(lsf);
-    lsf->path = hExtFileNameC(conn, extTable, extId);
+    lsf->path = path;
     lsf->extTable = cloneString(extTable);
     lsf->db = cloneString(db);
     lsf->id = extId;
     if ((lsf->fd = open(lsf->path, O_RDONLY)) < 0)
         errAbort("Couldn't open external file %s", lsf->path);
     slAddHead(&largeFileList, lsf);
     return lsf;
     }
 }
 
 static void *readOpenFileSection(int fd, off_t offset, size_t size, char *fileName, char *acc)
 /* Allocate a buffer big enough to hold a section of a file,
  * and read that section into it. */
 {
 void *buf;
@@ -1375,32 +1399,36 @@
     {
     sqlFreeResult(&sr);
     hFreeConn(&conn);
     return NULL;
     }
 HGID extId = sqlUnsigned(row[0]);
 off_t offset = sqlLongLong(row[1]);
 size_t size = sqlUnsigned(row[2]);
 sqlFreeResult(&sr);
 hFreeConn(&conn);
 
 /* look up extFile */
 char *extDb = dbTblParse(db, extFileTbl, &extFileTbl, dbBuf, sizeof(dbBuf));
 conn = hAllocConn(extDb);
 struct largeSeqFile *lsf = largeFileHandle(conn, extId, extFileTbl);
-char *buf = readOpenFileSection(lsf->fd, offset, size, lsf->path, acc);
 hFreeConn(&conn);
+
+if (lsf == NULL)
+    return NULL;
+
+char *buf = readOpenFileSection(lsf->fd, offset, size, lsf->path, acc);
 return faSeqFromMemText(buf, isDna);
 }
 
 static bioSeq *seqMustGet(char *db, char *acc, boolean isDna, char *seqTbl, char *extFileTbl)
 /* Return sequence from the specified seq and extFile tables.  The
  * seqTbl/extFileTbl arguments may include the database, in which case they
  * override what is in db (which could even be NULL).  Return Abort if not
  * found. */
 {
 bioSeq *seq = seqGet(db, acc, isDna, seqTbl, extFileTbl);
 if (seq == NULL)
     errAbort("can't find \"%s\" in seq table %s.%s", acc, db, seqTbl);
 return seq;
 }
 
@@ -1474,30 +1502,33 @@
 /* Return sequence as a fasta record in a string and it's database ID, or
  * NULL if not found. Optionally get genbank modification date. */
 {
 HGID extId;
 size_t size;
 off_t offset;
 char *extTable = NULL;
 /* try gbExtFile table first, as it tends to be  more performance sensitive */
 if (querySeqInfo(conn, acc, "gbSeq", "gbExtFile", retId, &extId, &size, &offset))
     extTable = "gbExtFile";
 else if (querySeqInfo(conn, acc, "seq", "extFile", retId, &extId, &size, &offset))
     extTable = "extFile";
 else
     return NULL;
 struct largeSeqFile *lsf = largeFileHandle(conn, extId, extTable);
+if (lsf == NULL)
+    return NULL;
+
 char *buf = readOpenFileSection(lsf->fd, offset, size, lsf->path, acc);
 return buf;
 }
 
 static char* mustGetSeqAndId(struct sqlConnection *conn, char *acc,
                              HGID *retId)
 /* Return sequence as a fasta record in a string and it's database ID,
  * abort if not found */
 {
 char *buf= getSeqAndId(conn, acc, retId);
 if (buf == NULL)
     errAbort("No sequence for %s in seq or gbSeq tables", acc);
 return buf;
 }