src/lib/udc.c 1.23
1.23 2009/11/06 05:08:02 angie
More changes motivated by udcFuse performance: added udcCacheAge, udcCacheTimeout and udcSetCacheTimeout. If cache files exist and are younger than the cache timeout threshold, don't fetch info from the remote server when opening, just use size and date from bitmap file. This saves 0.8s per open for ftp to NCBI. By default, cache timeout is 0 (same behavior as before -- always fetch info).
Index: src/lib/udc.c
===================================================================
RCS file: /projects/compbio/cvsroot/kent/src/lib/udc.c,v
retrieving revision 1.22
retrieving revision 1.23
diff -b -B -U 4 -r1.22 -r1.23
--- src/lib/udc.c 6 Nov 2009 04:50:52 -0000 1.22
+++ src/lib/udc.c 6 Nov 2009 05:08:02 -0000 1.23
@@ -85,8 +85,9 @@
};
static char *bitmapName = "bitmap";
static char *sparseDataName = "sparseData";
#define udcBitmapHeaderSize (64)
+static int cacheTimeout = 0;
/********* Section for local file protocol **********/
static char *assertLocalUrl(char *url)
@@ -659,8 +660,22 @@
file->bitmapFileName = fileNameInCacheDir(file, bitmapName);
file->sparseFileName = fileNameInCacheDir(file, sparseDataName);
}
+static int udcSizeFromBitmap(char *bitmapFileName)
+/* Look up the file size from the local cache bitmap file, or -1 if there
+ * is no cache for url. */
+{
+int ret = -1;
+struct udcBitmap *bits = udcBitmapOpen(bitmapFileName);
+if (bits != NULL)
+ ret = bits->fileSize;
+else
+ warn("Can't open bitmap file %s: %s\n", bitmapFileName, strerror(errno));
+udcBitmapClose(&bits);
+return ret;
+}
+
struct udcFile *udcFileMayOpen(char *url, char *cacheDir)
/* Open up a cached file. cacheDir may be null in which case udcDefaultDir() will be
* used. Return NULL if file doesn't exist. */
{
@@ -682,11 +697,12 @@
struct udcProtocol *prot;
prot = udcProtocolNew(protocol);
/* Figure out if anything exists. */
+boolean useCacheInfo = (udcCacheAge(url, cacheDir) < udcCacheTimeout());
struct udcRemoteFileInfo info;
ZeroVar(&info);
-if (!isTransparent)
+if (!isTransparent && !useCacheInfo)
{
if (!prot->fetchInfo(url, &info))
{
udcProtocolFree(&prot);
@@ -701,10 +717,8 @@
AllocVar(file);
file->url = cloneString(url);
file->protocol = protocol;
file->prot = prot;
-file->updateTime = info.updateTime;
-file->size = info.size;
if (isTransparent)
{
/* If transparent dummy up things so that the "sparse" file pointer is actually
* the file itself, which appears to be completely loaded in cache. */
@@ -716,8 +730,18 @@
}
else
{
udcPathAndFileNames(file, cacheDir, protocol, afterProtocol);
+ if (useCacheInfo)
+ {
+ file->updateTime = fileModTime(file->bitmapFileName);
+ file->size = udcSizeFromBitmap(file->bitmapFileName);
+ }
+ else
+ {
+ file->updateTime = info.updateTime;
+ file->size = info.size;
+ }
/* Make directory. */
makeDirsOnPath(file->cacheDir);
@@ -745,8 +769,10 @@
{
char *protocol, *afterProtocol, *colon;
struct udcFile *file;
udcParseUrl(url, &protocol, &afterProtocol, &colon);
+if (colon == NULL)
+ return NULL;
AllocVar(file);
udcPathAndFileNames(file, cacheDir, protocol, afterProtocol);
struct slName *list = NULL;
slAddHead(&list, slNameNew(file->bitmapFileName));
@@ -841,19 +867,33 @@
struct slName *sl, *slList = udcFileCacheFiles(url, cacheDir);
for (sl = slList; sl != NULL; sl = sl->next)
if (endsWith(sl->name, bitmapName))
{
- struct udcBitmap *bits = udcBitmapOpen(sl->name);
- if (bits != NULL)
- ret = bits->fileSize;
- else
- warn("Can't open bitmap file %s: %s\n", sl->name, strerror(errno));
- udcBitmapClose(&bits);
+ ret = udcSizeFromBitmap(sl->name);
+ break;
}
slNameFreeList(&slList);
return ret;
}
+unsigned long udcCacheAge(char *url, char *cacheDir)
+/* Return the age in seconds of the oldest cache file. If a cache file is
+ * missing, return the current time (seconds since the epoch). */
+{
+unsigned long now = clock1(), oldestTime = now;
+if (cacheDir == NULL)
+ cacheDir = udcDefaultDir();
+struct slName *sl, *slList = udcFileCacheFiles(url, cacheDir);
+if (slList == NULL)
+ return now;
+for (sl = slList; sl != NULL; sl = sl->next)
+ if (fileExists(sl->name))
+ oldestTime = min(fileModTime(sl->name), oldestTime);
+ else
+ return now;
+return (now - oldestTime);
+}
+
static void readBitsIntoBuf(FILE *f, int headerSize, int bitStart, int bitEnd,
Bits **retBits, int *retPartOffset)
/* Do some bit-to-byte offset conversions and read in all the bytes that
* have information in the bits we're interested in. */
@@ -1229,4 +1269,17 @@
defaultDir = path;
}
+int udcCacheTimeout()
+/* Get cache timeout (if local cache files are newer than this many seconds,
+ * we won't ping the remote server to check the file size and update time). */
+{
+return cacheTimeout;
+}
+
+void udcSetCacheTimeout(int timeout)
+/* Set cache timeout (if local cache files are newer than this many seconds,
+ * we won't ping the remote server to check the file size and update time). */
+{
+cacheTimeout = timeout;
+}