26c2f650359cc1c74fb31d96109bc0f8dedbc3d7
angie
  Thu May 30 10:32:19 2019 -0700
Adding BAM and VCF item counts to hubApi's list/tracks function.  Note: older index files may not contain counts.  refs #18869, #23521

diff --git src/hg/hubApi/list.c src/hg/hubApi/list.c
index e41e290..37e2bce 100644
--- src/hg/hubApi/list.c
+++ src/hg/hubApi/list.c
@@ -1,18 +1,20 @@
 /* manage endpoint /list/ functions */
 
 #include "dataApi.h"
+#include "bamFile.h"
+#include "htslib/tbx.h"
 
 static void hubPublicJsonData(struct jsonWrite *jw, struct hubPublic *el,
   int columnCount, char **columnNames)
 /* Print array data for one row from hubPublic table, order here
  * must be same as was stated in the columnName header element
  * This code should be in hg/lib/hubPublic.c (which does not exist)
  */
 {
 int i = 0;
 jsonWriteObjectStart(jw, NULL);
 jsonWriteString(jw, columnNames[i++], el->hubUrl);
 jsonWriteString(jw, columnNames[i++], el->shortLabel);
 jsonWriteString(jw, columnNames[i++], el->longLabel);
 jsonWriteString(jw, columnNames[i++], el->registrationTime);
 jsonWriteNumber(jw, columnNames[i++], (long long)el->dbCount);
@@ -321,116 +323,126 @@
 	jsonWriteString(jw, "track", table);
     jsonWriteNumber(jw, "dataTimeStamp", (long long)dataTimeStamp);
     freeMem(dataTime);
     jsonWriteNumber(jw, "chromCount", (long long)slCount(ciList));
     jsonWriteObjectStart(jw, "chromosomes");
     for ( ; el != NULL; el = el->next )
 	{
         jsonWriteNumber(jw, el->chrom, (long long)el->size);
 	}
     jsonWriteObjectEnd(jw);	/* chromosomes */
     apiFinishOutput(0, NULL, jw);
     }
 hFreeConn(&conn);
 }
 
-static long long bbiItemCount(char *bigDataUrl, char *type)
+static long long bbiItemCount(char *bigDataUrl, char *type, char *indexFileOrUrl)
 /* check the bigDataUrl to see what the itemCount is there */
 {
 long long itemCount = 0;
 struct errCatch *errCatch = errCatchNew();
 if (errCatchStart(errCatch))
     {
     if (allowedBigBedType(type))
         {
         struct bbiFile *bbi = NULL;
         bbi = bigBedFileOpen(bigDataUrl);
         itemCount = bigBedItemCount(bbi);
         bbiFileClose(&bbi);
         }
     else if (startsWithWord("bigWig", type))
         {
         struct bbiFile *bwf = bigWigFileOpen(bigDataUrl);
         struct bbiSummaryElement sum = bbiTotalSummary(bwf);
         itemCount = sum.validCount;
         bbiFileClose(&bwf);
         }
-    // NOTE: htslib does not appear to have a function to extract a count from BAI or TBI (tabix)
-    // indexes.  One could probably be added by adding code similar to samtools' idxstats subcommand,
-    // But in the meantime, this is not supported for types vcfTabix and bam.
+    else if (sameString("bam", type))
+        {
+        itemCount = bamFileItemCount(bigDataUrl, indexFileOrUrl);
+        }
+    else if (sameString("vcfTabix", type))
+        {
+        itemCount = vcfTabixItemCount(bigDataUrl, indexFileOrUrl);
+        }
     }
 errCatchEnd(errCatch);
+if (isNotEmpty(errCatch->message->string))
+    fprintf(stderr, "%s", errCatch->message->string);
 errCatchFree(&errCatch);
 return itemCount;
 }
 
 static long long bbiTableItemCount(struct sqlConnection *conn, char *type, char *tableName)
 /* Given a tableName that has a fileName column pointing to big*, bam or vcfTabix files, return the
  * total itemCount from all rows (BAM and VCF tables may have one row per chrom). */
 {
 long long itemCount = 0;
 char query[2048];
 sqlSafef(query, sizeof query, "select fileName from %s", tableName);
 struct sqlResult *sr = sqlGetResult(conn, query);
 char **row;
 while ((row = sqlNextRow(sr)) != NULL)
     {
-    itemCount += bbiItemCount(row[0], type);
+    itemCount += bbiItemCount(hReplaceGbdb(row[0]), type, NULL);
     }
 sqlFreeResult(&sr);
 return itemCount;
 }
 
 static long long dataItemCount(char *db, struct trackDb *tdb)
 /* determine how many items are in this data set */
 {
 boolean isContainer = tdbIsComposite(tdb) || tdbIsCompositeView(tdb);
 if (trackDbSetting(tdb, "container"))
     isContainer = TRUE;
 long long itemCount = 0;
 if (isContainer)	/* containers have no data items */
     return itemCount;
 if (sameWord("downloadsOnly", tdb->type))
     return itemCount;
 
-char *bigDataUrl = trackDbSetting(tdb, "bigDataUrl");
+char *bigDataUrl = hReplaceGbdb(trackDbSetting(tdb, "bigDataUrl"));
 if (isNotEmpty(bigDataUrl))
-    itemCount = bbiItemCount(bigDataUrl, tdb->type);
+    {
+    char *indexFileOrUrl = hReplaceGbdb(trackDbSetting(tdb, "bigDataIndex"));
+    itemCount = bbiItemCount(bigDataUrl, tdb->type, indexFileOrUrl);
+    }
 else
     {
     /* prepare for getting table row count, find table name */
     /* the trackDb might have a specific table defined */
     char *tableName = trackDbSetting(tdb, "table");
     if (isEmpty(tableName))
 	tableName = trackDbSetting(tdb, "track");
     if (isNotEmpty(tableName))
 	{
 	struct sqlConnection *conn = hAllocConnMaybe(db);
 	if (conn)
 	    {
             if ((startsWith("big", tdb->type) ||
                  sameString("vcfTabix", tdb->type) || sameString("bam", tdb->type)) &&
                 sqlColumnExists(conn, tableName, "fileName"))
                 {
                 itemCount = bbiTableItemCount(conn, tdb->type, tableName);
                 }
             else
                 {
                 /* punting on split tables, return zero */
                 struct hTableInfo *hti =
                     hFindTableInfoWithConn(conn, NULL, tableName);
-                if (hti && hti->isSplit)
+                if (!hti || hti->isSplit)
                     {
                     itemCount = 0;
                     }
                 else
                     {
                     char query[2048];
                     sqlSafef(query, sizeof(query), "select count(*) from %s", tableName);
                     itemCount = sqlQuickNum(conn, query);
                     }
                 }
             hFreeConn(&conn);
 	    }
 	}
     }
 return itemCount;