ubik: remove unnecessary lseeks in uphys_open
[openafs.git] / src / ubik / phys.c
index 636a6a3..62063bb 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * Copyright 2000, International Business Machines Corporation and others.
  * All Rights Reserved.
- * 
+ *
  * This software has been released under the terms of the IBM Public
  * License.  For details, see the LICENSE file in the top-level source
  * directory or online at http://www.openafs.org/dl/license10.html
 #include <afsconfig.h>
 #include <afs/param.h>
 
-RCSID
-    ("$Header$");
-
-#include <sys/types.h>
-#ifdef AFS_NT40_ENV
-#include <winsock2.h>
-#include <io.h>
-#include <fcntl.h>
-#else
-#include <sys/file.h>
-#include <netinet/in.h>
-#endif
-#include <sys/stat.h>
-
-/* #ifdef AFS_PTHREAD_ENV */
-#if 0   /* temporary hack - klm */
-/* nothing */
-#else
+#include <roken.h>
+
 #include <lwp.h>
-#endif
 
 #include <lock.h>
-#include <errno.h>
-#include <string.h>
+#include <afs/afsutil.h>
 
 #define        UBIK_INTERNALS 1
 #include "ubik.h"
 
-/* these routines are called via the proc ptr in the ubik_dbase structure.  They provide access to
- * the physical disk, by converting the file numbers being processed (>= 0 for user data space, < 0
+/*! \file
+ * These routines are called via the proc ptr in the ubik_dbase structure.  They provide access to
+ * the physical disk, by converting the file numbers being processed ( >= 0 for user data space, < 0
  * for ubik system files, such as the log) to actual pathnames to open, read, write, truncate, sync,
  * etc.
  */
@@ -51,17 +34,28 @@ 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];
 
-/* beware, when using this function, of the header in front of most files */
+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.
+ */
 static int
-uphys_open(register struct ubik_dbase *adbase, afs_int32 afid)
+uphys_open(struct ubik_dbase *adbase, afs_int32 afid)
 {
-    char temp[20];
-    register int fd;
+    int fd;
     static int initd;
-    register int i;
-    register struct fdcache *tfd;
+    int i;
+    struct fdcache *tfd;
     struct fdcache *bestfd;
 
     /* initialize package */
@@ -78,15 +72,14 @@ uphys_open(register 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;
        }
     }
 
     /* not found, open it and try to enter in cache */
-    afs_snprintf(pbuffer, sizeof(pbuffer), "%s.DB%s%d", adbase->pathName, 
-                (afid<0)?"SYS":"", (afid<0)?-afid:afid);
+    snprintf(pbuffer, sizeof(pbuffer), "%s.DB%s%d", adbase->pathName,
+            (afid<0)?"SYS":"", (afid<0)?-afid:afid);
     fd = open(pbuffer, O_CREAT | O_RDWR, 0600);
     if (fd < 0) {
        /* try opening read-only */
@@ -115,7 +108,7 @@ uphys_open(register struct ubik_dbase *adbase, afs_int32 afid)
     }
     if (bestfd) {              /* found a usable slot */
        tfd = bestfd;
-       if (tfd->fd >= 0) 
+       if (tfd->fd >= 0)
            close(tfd->fd);
        tfd->fd = fd;
        tfd->refCount = 1;      /* us */
@@ -126,18 +119,20 @@ uphys_open(register struct ubik_dbase *adbase, afs_int32 afid)
     return fd;
 }
 
-/* close the file, maintaining ref count in cache structure */
-int
-uphys_close(register int afd)
+/*!
+ * \brief Close the file, maintaining ref count in cache structure.
+ */
+static int
+uphys_close(int afd)
 {
-    register int i;
-    register struct fdcache *tfd;
+    int i;
+    struct fdcache *tfd;
 
     if (afd < 0)
        return EBADF;
     tfd = fdcache;
     for (i = 0; i < MAXFDCACHE; i++, tfd++) {
-       if (tfd->fd == afd) 
+       if (tfd->fd == afd) {
            if (tfd->fileID != -10000) {
                tfd->refCount--;
                return 0;
@@ -153,6 +148,7 @@ uphys_close(register int afd)
                tfd->fd = -1;
                break;
            }
+       }
     }
     return close(afd);
 }
@@ -160,9 +156,9 @@ uphys_close(register int afd)
 int
 uphys_stat(struct ubik_dbase *adbase, afs_int32 afid, struct ubik_stat *astat)
 {
-    register int fd;
+    int fd;
     struct stat tstat;
-    register afs_int32 code;
+    afs_int32 code;
 
     fd = uphys_open(adbase, afid);
     if (fd < 0)
@@ -172,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;
@@ -182,11 +177,11 @@ uphys_stat(struct ubik_dbase *adbase, afs_int32 afid, struct ubik_stat *astat)
 }
 
 int
-uphys_read(register struct ubik_dbase *adbase, afs_int32 afile,
-          register char *abuffer, afs_int32 apos, afs_int32 alength)
+uphys_read(struct ubik_dbase *adbase, afs_int32 afile,
+          void *abuffer, afs_int32 apos, afs_int32 alength)
 {
-    register int fd;
-    register afs_int32 code;
+    int fd;
+    afs_int32 code;
 
     fd = uphys_open(adbase, afile);
     if (fd < 0)
@@ -202,11 +197,11 @@ uphys_read(register struct ubik_dbase *adbase, afs_int32 afile,
 }
 
 int
-uphys_write(register struct ubik_dbase *adbase, afs_int32 afile,
-           register char *abuffer, afs_int32 apos, afs_int32 alength)
+uphys_write(struct ubik_dbase *adbase, afs_int32 afile,
+           void *abuffer, afs_int32 apos, afs_int32 alength)
 {
-    register int fd;
-    register afs_int32 code;
+    int fd;
+    afs_int32 code;
     afs_int32 length;
 
     fd = uphys_open(adbase, afile);
@@ -226,10 +221,17 @@ uphys_write(register struct ubik_dbase *adbase, afs_int32 afile,
 }
 
 int
-uphys_truncate(register struct ubik_dbase *adbase, afs_int32 afile,
+uphys_truncate(struct ubik_dbase *adbase, afs_int32 afile,
               afs_int32 asize)
 {
-    register afs_int32 code, fd;
+    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;
@@ -238,25 +240,35 @@ uphys_truncate(register struct ubik_dbase *adbase, afs_int32 afile,
     return code;
 }
 
-/* get number of dbase files */
+/*!
+ * \brief Get number of dbase files.
+ *
+ * \todo Really should scan dir for data.
+ */
 int
-uphys_getnfiles(register struct ubik_dbase *adbase)
+uphys_getnfiles(struct ubik_dbase *adbase)
 {
     /* really should scan dir for data */
     return 1;
 }
 
-/* get database label, with aversion in host order */
+/*!
+ * \brief Get database label, with \p aversion in host order.
+ */
 int
-uphys_getlabel(register struct ubik_dbase *adbase, afs_int32 afile,
+uphys_getlabel(struct ubik_dbase *adbase, afs_int32 afile,
               struct ubik_version *aversion)
 {
     struct ubik_hdr thdr;
-    register afs_int32 code, fd;
+    afs_int32 code, fd;
 
     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);
@@ -268,21 +280,30 @@ uphys_getlabel(register struct ubik_dbase *adbase, afs_int32 afile,
     return 0;
 }
 
-/* label database, with aversion in host order */
+/*!
+ * \brief Label database, with \p aversion in host order.
+ */
 int
-uphys_setlabel(register struct ubik_dbase *adbase, afs_int32 afile,
+uphys_setlabel(struct ubik_dbase *adbase, afs_int32 afile,
               struct ubik_version *aversion)
 {
     struct ubik_hdr thdr;
-    register afs_int32 code, fd;
+    afs_int32 code, fd;
 
     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);
@@ -293,9 +314,15 @@ uphys_setlabel(register struct ubik_dbase *adbase, afs_int32 afile,
 }
 
 int
-uphys_sync(register struct ubik_dbase *adbase, afs_int32 afile)
+uphys_sync(struct ubik_dbase *adbase, afs_int32 afile)
 {
-    register afs_int32 code, fd;
+    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);
@@ -303,10 +330,10 @@ uphys_sync(register struct ubik_dbase *adbase, afs_int32 afile)
 }
 
 void
-uphys_invalidate(register struct ubik_dbase *adbase, afs_int32 afid)
+uphys_invalidate(struct ubik_dbase *adbase, afs_int32 afid)
 {
-    register int i;
-    register struct fdcache *tfd;
+    int i;
+    struct fdcache *tfd;
 
     /* scan file descr cache */
     for (tfd = fdcache, i = 0; i < MAXFDCACHE; i++, tfd++) {
@@ -320,3 +347,58 @@ uphys_invalidate(register 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;
+}