ubik: remove unnecessary lseeks in uphys_open
[openafs.git] / src / ubik / phys.c
index b8fbef4..62063bb 100644 (file)
@@ -34,8 +34,18 @@ static struct fdcache {
     int refCount;
 } fdcache[MAXFDCACHE];
 
+/* Cache a stdio handle for a given database file, for uphys_buf_append
+ * operations. We only use buf_append for one file at a time, so only try to
+ * cache a single file handle, since that's all we should need. */
+static struct buf_fdcache {
+    int fileID;
+    FILE *stream;
+} buf_fdcache;
+
 static char pbuffer[1024];
 
+static int uphys_buf_flush(struct ubik_dbase *adbase, afs_int32 afid);
+
 /*!
  * \warning Beware, when using this function, of the header in front of most files.
  */
@@ -62,7 +72,6 @@ uphys_open(struct ubik_dbase *adbase, afs_int32 afid)
     /* scan file descr cache */
     for (tfd = fdcache, i = 0; i < MAXFDCACHE; i++, tfd++) {
        if (afid == tfd->fileID && tfd->refCount == 0) {        /* don't use open fd */
-           lseek(tfd->fd, 0, 0);       /* reset ptr just like open would have */
            tfd->refCount++;
            return tfd->fd;
        }
@@ -159,7 +168,6 @@ uphys_stat(struct ubik_dbase *adbase, afs_int32 afid, struct ubik_stat *astat)
     if (code < 0) {
        return code;
     }
-    astat->mtime = tstat.st_mtime;
     code = tstat.st_size - HDRSIZE;
     if (code < 0)
        astat->size = 0;
@@ -217,6 +225,13 @@ uphys_truncate(struct ubik_dbase *adbase, afs_int32 afile,
               afs_int32 asize)
 {
     afs_int32 code, fd;
+
+    /* Just in case there's memory-buffered data for this file, flush it before
+     * truncating. */
+    if (uphys_buf_flush(adbase, afile) < 0) {
+        return UIOERROR;
+    }
+
     fd = uphys_open(adbase, afile);
     if (fd < 0)
        return UNOENT;
@@ -250,6 +265,10 @@ uphys_getlabel(struct ubik_dbase *adbase, afs_int32 afile,
     fd = uphys_open(adbase, afile);
     if (fd < 0)
        return UNOENT;
+    if (lseek(fd, 0, 0) < 0) {
+       uphys_close(fd);
+       return EIO;
+    }
     code = read(fd, &thdr, sizeof(thdr));
     if (code != sizeof(thdr)) {
        uphys_close(fd);
@@ -274,10 +293,17 @@ uphys_setlabel(struct ubik_dbase *adbase, afs_int32 afile,
     fd = uphys_open(adbase, afile);
     if (fd < 0)
        return UNOENT;
+
+    memset(&thdr, 0, sizeof(thdr));
+
     thdr.version.epoch = htonl(aversion->epoch);
     thdr.version.counter = htonl(aversion->counter);
     thdr.magic = htonl(UBIK_MAGIC);
     thdr.size = htons(HDRSIZE);
+    if (lseek(fd, 0, 0) < 0) {
+       uphys_close(fd);
+       return EIO;
+    }
     code = write(fd, &thdr, sizeof(thdr));
     fsync(fd);                 /* preserve over crash */
     uphys_close(fd);
@@ -291,6 +317,12 @@ int
 uphys_sync(struct ubik_dbase *adbase, afs_int32 afile)
 {
     afs_int32 code, fd;
+
+    /* Flush any in-memory data, so we can sync it. */
+    if (uphys_buf_flush(adbase, afile) < 0) {
+        return -1;
+    }
+
     fd = uphys_open(adbase, afile);
     code = fsync(fd);
     uphys_close(fd);
@@ -315,3 +347,58 @@ uphys_invalidate(struct ubik_dbase *adbase, afs_int32 afid)
        }
     }
 }
+
+static FILE *
+uphys_buf_append_open(struct ubik_dbase *adbase, afs_int32 afid)
+{
+    /* If we have a cached handle open for this file, just return it. */
+    if (buf_fdcache.stream && buf_fdcache.fileID == afid) {
+        return buf_fdcache.stream;
+    }
+
+    /* Otherwise, close the existing handle, and open a new handle for the
+     * given file. */
+
+    if (buf_fdcache.stream) {
+        fclose(buf_fdcache.stream);
+    }
+
+    snprintf(pbuffer, sizeof(pbuffer), "%s.DB%s%d", adbase->pathName,
+            (afid<0)?"SYS":"", (afid<0)?-afid:afid);
+    buf_fdcache.stream = fopen(pbuffer, "a");
+    buf_fdcache.fileID = afid;
+    return buf_fdcache.stream;
+}
+
+static int
+uphys_buf_flush(struct ubik_dbase *adbase, afs_int32 afid)
+{
+    if (buf_fdcache.stream && buf_fdcache.fileID == afid) {
+        int code = fflush(buf_fdcache.stream);
+        if (code) {
+            return -1;
+        }
+    }
+    return 0;
+}
+
+/* Append the given data to the given database file, allowing the data to be
+ * buffered in memory. */
+int
+uphys_buf_append(struct ubik_dbase *adbase, afs_int32 afid, void *adata,
+                 afs_int32 alength)
+{
+    FILE *stream;
+    size_t code;
+
+    stream = uphys_buf_append_open(adbase, afid);
+    if (!stream) {
+        return -1;
+    }
+
+    code = fwrite(adata, alength, 1, stream);
+    if (code != 1) {
+        return -1;
+    }
+    return alength;
+}