For whatever reason, part of the original patch was incorrect.  Here's
the update against apr-util HEAD...

Again there is no storage/recovery of these page size parameters yet,
and we have yet to define an API for opening/creating an SDBM with
such alternatives.  It should be obvious in the open call where I've hacked
in our default values, for anyone to experiment with.

Immediate beneficiaries include mod_ssl and dav, where pages may need
to be much larger than the default.

Bill

At 02:56 PM 9/19/2003, William A. Rowe, Jr. wrote:
>As a few here already know, we used the 'Standard' page size for our
>apr-util SDBM implementation.  This assures that you can modify our
>sdbm files from perl and other tools.
>
>However, it's pretty clear that 1024 just doesn't cut it when it comes
>to huge objects from ssl caching and other sorts of large blobs.  The
>modssl project (1.3) had tweaked sdbm to take larger page sizes, but
>this leads to an inflexible implementation (another fixed page size, but
>incompatible with other implementations.)
>
>I'd like to see apr-util support alternate sized dbm pages, but without
>making fixed assumptions about those sizes (other than this - the 
>structure uses short's for offsets, so the page size does have a cap.)
>
>The attached patch allows the SDBM to be of any arbitrary data and
>directory page sizes.  However, I've not hacked in any method of
>declaring what those sizes should be (they are the 'standard' defaults
>at the moment.)
>
>What do folks believe is the most rational approach to expanding support 
>to create an sdbm with alternate page sizes?  And how best can we embed 
>that info into the sdbm so that later accesses to the file use the correct
>page size?  My current thought is to embed a NULL-key record at the head
>of the file, with a specific known value element containing some identifier
>string such as "APR-SDBM" followed by two ints, the page and data len.
>If that record is missing (or created with default sizes), the file is treated 
>as a standard sdbm with 1024/4096 sized pages.
? foo
? variable_sdbm.patch
Index: dbm/sdbm/sdbm.c
===================================================================
RCS file: /home/cvs/apr-util/dbm/sdbm/sdbm.c,v
retrieving revision 1.26
diff -u -r1.26 sdbm.c
--- dbm/sdbm/sdbm.c     1 Jan 2003 00:02:19 -0000       1.26
+++ dbm/sdbm/sdbm.c     16 Oct 2003 17:19:20 -0000
@@ -71,7 +71,6 @@
 #include "sdbm_private.h"
 
 #include <string.h>     /* for memset() */
-#include <stdlib.h>     /* for malloc() and free() */
 
 /*
  * forward
@@ -92,8 +91,8 @@
 #define sdbm_dirfno(db)        ((db)->dirf)
 #define sdbm_pagfno(db)        ((db)->pagf)
 
-#define OFF_PAG(off)   (apr_off_t) (off) * PBLKSIZ
-#define OFF_DIR(off)   (apr_off_t) (off) * DBLKSIZ
+#define OFF_PAG(db,off)        ((apr_off_t) (off) * (db)->pblksiz)
+#define OFF_DIR(db,off)        ((apr_off_t) (off) * (db)->dblksiz)
 
 static long masks[] = {
         000000000000, 000000000001, 000000000003, 000000000007,
@@ -120,7 +119,6 @@
         (void) apr_file_unlock(db->dirf);
     (void) apr_file_close(db->dirf);
     (void) apr_file_close(db->pagf);
-    free(db);
 
     return APR_SUCCESS;
 }
@@ -133,11 +131,28 @@
 
     *pdb = NULL;
 
-    db = malloc(sizeof(*db));
-    memset(db, 0, sizeof(*db));
-
+    /* Allocate a single buffer for the structure and NULL it
+     */
+    db = apr_palloc(p, sizeof(apr_sdbm_t));
+    memset(db, 0, sizeof(apr_sdbm_t));
     db->pool = p;
 
+    /* Determine the dblksiz/pblksiz (unimplemented), 
+     * then allocate and null the buffers.
+     * Because we ultimately need to read these after the db is opened,
+     * they can't be allocated at the time we allocate db.
+     * The default sizes below indicate the "standard" sdbm parameters
+     * that are respected by perl and most sdbm implementations.
+     */
+    db->dblksiz = 4096;
+    db->pblksiz = 1024;
+
+    db->pagbuf = apr_palloc(db->pool, db->pblksiz * 3 + db->dblksiz);
+    memset(db->pagbuf, 0, db->pblksiz + db->dblksiz);
+    db->pagtmp = db->pagbuf + db->pblksiz;
+    db->pagwrk = db->pagtmp + db->pblksiz;
+    db->dirbuf = db->pagwrk + db->pblksiz;
+
     /*
      * adjust user flags so that WRONLY becomes RDWR, 
      * as required by this package. Also set our internal
@@ -205,7 +220,6 @@
     if (db->pagf != NULL) {
         (void) apr_file_close(db->pagf);
     }
-    free(db);
     return status;
 }
 
@@ -236,7 +250,7 @@
         return status;
 
     if ((status = getpage(db, exhash(key))) == APR_SUCCESS) {
-        *val = getpair(db->pagbuf, key);
+        *val = getpair(db->pagbuf, key, db->pblksiz);
         /* ### do we want a not-found result? */
     }
 
@@ -248,10 +262,10 @@
 static apr_status_t write_page(apr_sdbm_t *db, const char *buf, long pagno)
 {
     apr_status_t status;
-    apr_off_t off = OFF_PAG(pagno);
+    apr_off_t off = OFF_PAG(db, pagno);
     
     if ((status = apr_file_seek(db->pagf, APR_SET, &off)) == APR_SUCCESS)
-        status = apr_file_write_full(db->pagf, buf, PBLKSIZ, NULL);
+        status = apr_file_write_full(db->pagf, buf, db->pblksiz, NULL);
 
     return status;
 }
@@ -270,7 +284,7 @@
         return status;
 
     if ((status = getpage(db, exhash(key))) == APR_SUCCESS) {
-        if (!delpair(db->pagbuf, key))
+        if (!delpair(db->pagbuf, key, db->pblksiz))
             /* ### should we define some APRUTIL codes? */
             status = APR_EGENERAL;
         else
@@ -295,9 +309,11 @@
         return APR_EINVAL;
     need = key.dsize + val.dsize;
     /*
-     * is the pair too big (or too small) for this database ??
+     * Is the pair too big (or too small) for this database ??
+     * This is derived from the original MAXPAIR calculation.
+     * At least MS compiler screamed that sizeof left the RHS unsigned.
      */
-    if (need < 0 || need > PAIRMAX)
+    if ((need < 0) || (need > db->pblksiz - (int)sizeof(short) * 8))
         return APR_EINVAL;
 
     if ((status = apr_sdbm_lock(db, APR_FLOCK_EXCLUSIVE)) != APR_SUCCESS)
@@ -310,22 +326,23 @@
          * first. If it is not there, ignore.
          */
         if (flags == APR_SDBM_REPLACE)
-            (void) delpair(db->pagbuf, key);
-        else if (!(flags & APR_SDBM_INSERTDUP) && duppair(db->pagbuf, key)) {
+            (void) delpair(db->pagbuf, key, db->pblksiz);
+        else if (!(flags & APR_SDBM_INSERTDUP) 
+              && duppair(db->pagbuf, key, db->pblksiz)) {
             status = APR_EEXIST;
             goto error;
         }
         /*
          * if we do not have enough room, we have to split.
          */
-        if (!fitpair(db->pagbuf, need))
+        if (!fitpair(db->pagbuf, need, db->pblksiz))
             if ((status = makroom(db, hash, need)) != APR_SUCCESS)
                 goto error;
         /*
          * we have enough room or split is successful. insert the key,
          * and update the page file.
          */
-        (void) putpair(db->pagbuf, key, val);
+        (void) putpair(db->pagbuf, key, val, db->pblksiz);
 
         status = write_page(db, db->pagbuf, db->pagbno);
     }
@@ -344,8 +361,9 @@
 static apr_status_t makroom(apr_sdbm_t *db, long hash, int need)
 {
     long newp;
-    char twin[PBLKSIZ];
+    char *twin = db->pagtmp;
     char *pag = db->pagbuf;
+    char *wrk = db->pagwrk;
     char *new = twin;
     register int smax = SPLTMAX;
     apr_status_t status;
@@ -354,7 +372,7 @@
         /*
          * split the current page
          */
-        (void) splpage(pag, new, db->hmask + 1);
+        (void) splpage(pag, new, wrk, db->hmask + 1, db->pblksiz);
         /*
          * address of the new page
          */
@@ -374,7 +392,7 @@
                 return status;
                     
             db->pagbno = newp;
-            (void) memcpy(pag, new, PBLKSIZ);
+            (void) memcpy(pag, new, db->pblksiz);
         }
         else {
             if ((status = write_page(db, new, newp)) != APR_SUCCESS)
@@ -386,7 +404,7 @@
         /*
          * see if we have enough room now
          */
-        if (fitpair(pag, need))
+        if (fitpair(pag, need, db->pblksiz))
             return APR_SUCCESS;
         /*
          * try again... update curbit and hmask as getpage would have
@@ -452,7 +470,7 @@
     /*
      * start at page 0
      */
-    if ((status = read_from(db->pagf, db->pagbuf, OFF_PAG(0), PBLKSIZ))
+    if ((status = read_from(db->pagf, db->pagbuf, OFF_PAG(db, 0), db->pblksiz))
                 == APR_SUCCESS) {
         db->pagbno = 0;
         db->blkptr = 0;
@@ -512,11 +530,11 @@
          * ### joe: this assumption was surely never correct? but
          * ### we make it so in read_from anyway.
          */
-        if ((status = read_from(db->pagf, db->pagbuf, OFF_PAG(pagb), PBLKSIZ)) 
+        if ((status = read_from(db->pagf, db->pagbuf, OFF_PAG(db, pagb), 
db->pblksiz)) 
                     != APR_SUCCESS)
             return status;
 
-        if (!chkpage(db->pagbuf))
+        if (!chkpage(db->pagbuf, db->pblksiz))
             return APR_ENOSPC; /* ### better error? */
         db->pagbno = pagb;
 
@@ -531,10 +549,10 @@
     register long dirb;
 
     c = dbit / BYTESIZ;
-    dirb = c / DBLKSIZ;
+    dirb = c / db->dblksiz;
 
     if (dirb != db->dirbno) {
-        if (read_from(db->dirf, db->dirbuf, OFF_DIR(dirb), DBLKSIZ)
+        if (read_from(db->dirf, db->dirbuf, OFF_DIR(db, dirb), db->dblksiz)
                     != APR_SUCCESS)
             return 0;
 
@@ -543,7 +561,7 @@
         debug(("dir read: %d\n", dirb));
     }
 
-    return db->dirbuf[c % DBLKSIZ] & (1 << dbit % BYTESIZ);
+    return db->dirbuf[c % db->dblksiz] & (1 << dbit % BYTESIZ);
 }
 
 static apr_status_t setdbit(apr_sdbm_t *db, long dbit)
@@ -554,10 +572,10 @@
     apr_off_t off;
 
     c = dbit / BYTESIZ;
-    dirb = c / DBLKSIZ;
+    dirb = c / db->dblksiz;
 
     if (dirb != db->dirbno) {
-        if ((status = read_from(db->dirf, db->dirbuf, OFF_DIR(dirb), DBLKSIZ))
+        if ((status = read_from(db->dirf, db->dirbuf, OFF_DIR(db, dirb), 
db->dblksiz))
                     != APR_SUCCESS)
             return status;
 
@@ -566,14 +584,14 @@
         debug(("dir read: %d\n", dirb));
     }
 
-    db->dirbuf[c % DBLKSIZ] |= (1 << dbit % BYTESIZ);
+    db->dirbuf[c % db->dblksiz] |= (1 << dbit % BYTESIZ);
 
     if (dbit >= db->maxbno)
-        db->maxbno += DBLKSIZ * BYTESIZ;
+        db->maxbno += db->dblksiz * BYTESIZ;
 
-    off = OFF_DIR(dirb);
+    off = OFF_DIR(db, dirb);
     if ((status = apr_file_seek(db->dirf, APR_SET, &off)) == APR_SUCCESS)
-        status = apr_file_write_full(db->dirf, db->dirbuf, DBLKSIZ, NULL);
+        status = apr_file_write_full(db->dirf, db->dirbuf, db->dblksiz, NULL);
 
     return status;
 }
@@ -587,7 +605,7 @@
     apr_status_t status;
     for (;;) {
         db->keyptr++;
-        *key = getnkey(db->pagbuf, db->keyptr);
+        *key = getnkey(db->pagbuf, db->keyptr, db->pblksiz);
         if (key->dptr != NULL)
             return APR_SUCCESS;
         /*
@@ -597,7 +615,7 @@
          */
         db->keyptr = 0;
         if (db->pagbno != db->blkptr++) {
-            apr_off_t off = OFF_PAG(db->blkptr);
+            apr_off_t off = OFF_PAG(db, db->blkptr);
             if ((status = apr_file_seek(db->pagf, APR_SET, &off) 
                         != APR_SUCCESS))
                 return status;
@@ -605,10 +623,10 @@
 
         db->pagbno = db->blkptr;
         /* ### EOF acceptable here too? */
-        if ((status = apr_file_read_full(db->pagf, db->pagbuf, PBLKSIZ, NULL))
+        if ((status = apr_file_read_full(db->pagf, db->pagbuf, db->pblksiz, 
NULL))
                     != APR_SUCCESS)
             return status;
-        if (!chkpage(db->pagbuf))
+        if (!chkpage(db->pagbuf, db->pblksiz))
             return APR_EGENERAL;     /* ### need better error */
     }
 
@@ -623,4 +641,3 @@
      */
     return (db->flags & SDBM_RDONLY) != 0;
 }
-
Index: dbm/sdbm/sdbm_pair.c
===================================================================
RCS file: /home/cvs/apr-util/dbm/sdbm/sdbm_pair.c,v
retrieving revision 1.6
diff -u -r1.6 sdbm_pair.c
--- dbm/sdbm/sdbm_pair.c        1 Jan 2003 00:02:19 -0000       1.6
+++ dbm/sdbm/sdbm_pair.c        16 Oct 2003 17:19:20 -0000
@@ -75,7 +75,7 @@
 /* 
  * forward 
  */
-static int seepair(char *, int, char *, int);
+static int seepair(char *, int, char *, int, int);
 
 /*
  * page format:
@@ -98,16 +98,17 @@
  */
 
 int
-fitpair(pag, need)
+fitpair(pag, need, pblksz)
 char *pag;
 int need;
+int pblksz;
 {
-       register int n;
-       register int off;
-       register int avail;
        register short *ino = (short *) pag;
+       register int n = ino[0];
+       register int avail;
+       register int off;
 
-       off = ((n = ino[0]) > 0) ? ino[n] : PBLKSIZ;
+       off = (n > 0) ? ino[n] : pblksz;
        avail = off - (n + 1) * sizeof(short);
        need += 2 * sizeof(short);
 
@@ -117,16 +118,17 @@
 }
 
 void
-putpair(pag, key, val)
+putpair(pag, key, val, pblksz)
 char *pag;
 apr_sdbm_datum_t key;
 apr_sdbm_datum_t val;
+int pblksz;
 {
-       register int n;
-       register int off;
        register short *ino = (short *) pag;
+       register int n = ino[0];
+       register int off;
 
-       off = ((n = ino[0]) > 0) ? ino[n] : PBLKSIZ;
+       off = (n > 0) ? ino[n] : pblksz;
 /*
  * enter the key first
  */
@@ -146,19 +148,20 @@
 }
 
 apr_sdbm_datum_t
-getpair(pag, key)
+getpair(pag, key, pblksz)
 char *pag;
 apr_sdbm_datum_t key;
+int pblksz;
 {
-       register int i;
-       register int n;
        apr_sdbm_datum_t val;
        register short *ino = (short *) pag;
+       register int n = ino[0];
+       register int i;
 
-       if ((n = ino[0]) == 0)
+       if (n == 0)
                return sdbm_nullitem;
 
-       if ((i = seepair(pag, n, key.dptr, key.dsize)) == 0)
+       if ((i = seepair(pag, n, key.dptr, key.dsize, pblksz)) == 0)
                return sdbm_nullitem;
 
        val.dptr = pag + ino[i + 1];
@@ -167,28 +170,31 @@
 }
 
 int
-duppair(pag, key)
+duppair(pag, key, pblksz)
 char *pag;
 apr_sdbm_datum_t key;
+int pblksz;
 {
        register short *ino = (short *) pag;
-       return ino[0] > 0 && seepair(pag, ino[0], key.dptr, key.dsize) > 0;
+       return ino[0] > 0 
+            && seepair(pag, ino[0], key.dptr, key.dsize, pblksz) > 0;
 }
 
 apr_sdbm_datum_t
-getnkey(pag, num)
+getnkey(pag, num, pblksz)
 char *pag;
 int num;
+int pblksz;
 {
+       register short *ino = (short *) pag;
        apr_sdbm_datum_t key;
        register int off;
-       register short *ino = (short *) pag;
 
        num = num * 2 - 1;
        if (ino[0] == 0 || num > ino[0])
                return sdbm_nullitem;
 
-       off = (num > 1) ? ino[num - 1] : PBLKSIZ;
+       off = (num > 1) ? ino[num - 1] : pblksz;
 
        key.dptr = pag + ino[num];
        key.dsize = off - ino[num];
@@ -197,18 +203,19 @@
 }
 
 int
-delpair(pag, key)
+delpair(pag, key, pblksz)
 char *pag;
 apr_sdbm_datum_t key;
+int pblksz;
 {
-       register int n;
-       register int i;
        register short *ino = (short *) pag;
+       register int n = ino[0];
+       register int i;
 
-       if ((n = ino[0]) == 0)
+       if (n == 0)
                return 0;
 
-       if ((i = seepair(pag, n, key.dptr, key.dsize)) == 0)
+       if ((i = seepair(pag, n, key.dptr, key.dsize, pblksz)) == 0)
                return 0;
 /*
  * found the key. if it is the last entry
@@ -219,7 +226,7 @@
  */
        if (i < n - 1) {
                register int m;
-               register char *dst = pag + (i == 1 ? PBLKSIZ : ino[i - 1]);
+               register char *dst = pag + (i == 1 ? pblksz : ino[i - 1]);
                register char *src = pag + ino[i + 1];
                register int   zoo = dst - src;
 
@@ -269,14 +276,15 @@
  * return 0 if not found.
  */
 static int
-seepair(pag, n, key, siz)
+seepair(pag, n, key, siz, pblksz)
 char *pag;
 register int n;
 register char *key;
 register int siz;
+int pblksz;
 {
        register int i;
-       register int off = PBLKSIZ;
+       register int off = pblksz;
        register short *ino = (short *) pag;
 
        for (i = 1; i < n; i += 2) {
@@ -289,22 +297,24 @@
 }
 
 void
-splpage(pag, new, sbit)
+splpage(pag, new, wrk, sbit, pblksz)
 char *pag;
 char *new;
+char *wrk;
 long sbit;
+int pblksz;
 {
        apr_sdbm_datum_t key;
        apr_sdbm_datum_t val;
 
        register int n;
-       register int off = PBLKSIZ;
-       char cur[PBLKSIZ];
+       register int off = pblksz;
+       char *cur = wrk;
        register short *ino = (short *) cur;
 
-       (void) memcpy(cur, pag, PBLKSIZ);
-       (void) memset(pag, 0, PBLKSIZ);
-       (void) memset(new, 0, PBLKSIZ);
+       (void) memcpy(cur, pag, pblksz);
+       (void) memset(pag, 0, pblksz);
+       (void) memset(new, 0, pblksz);
 
        n = ino[0];
        for (ino++; n > 0; ino += 2) {
@@ -315,7 +325,8 @@
 /*
  * select the page pointer (by looking at sbit) and insert
  */
-               (void) putpair((exhash(key) & sbit) ? new : pag, key, val);
+               (void) putpair((exhash(key) & sbit) ? new : pag, 
+                               key, val, pblksz);
 
                off = ino[1];
                n -= 2;
@@ -333,18 +344,19 @@
  * this could be made more rigorous.
  */
 int
-chkpage(pag)
+chkpage(pag, pblksz)
 char *pag;
+int pblksz;
 {
-       register int n;
-       register int off;
        register short *ino = (short *) pag;
+       register int n = ino[0];
+       register int off;
 
-       if ((n = ino[0]) < 0 || n > PBLKSIZ / sizeof(short))
+       if (n < 0 || n > pblksz / (int)sizeof(short))
                return 0;
 
        if (n > 0) {
-               off = PBLKSIZ;
+               off = pblksz;
                for (ino++; n > 0; ino += 2) {
                        if (ino[0] > off || ino[1] > off ||
                            ino[1] > ino[0])
Index: dbm/sdbm/sdbm_pair.h
===================================================================
RCS file: /home/cvs/apr-util/dbm/sdbm/sdbm_pair.h,v
retrieving revision 1.5
diff -u -r1.5 sdbm_pair.h
--- dbm/sdbm/sdbm_pair.h        1 Jan 2003 00:02:19 -0000       1.5
+++ dbm/sdbm/sdbm_pair.h        16 Oct 2003 17:19:20 -0000
@@ -65,14 +65,14 @@
 #define putpair sdbm__putpair
 #define splpage sdbm__splpage
 
-int fitpair(char *, int);
-void  putpair(char *, apr_sdbm_datum_t, apr_sdbm_datum_t);
-apr_sdbm_datum_t getpair(char *, apr_sdbm_datum_t);
-int  delpair(char *, apr_sdbm_datum_t);
-int  chkpage (char *);
-apr_sdbm_datum_t getnkey(char *, int);
-void splpage(char *, char *, long);
-int duppair(char *, apr_sdbm_datum_t);
+int fitpair(char *, int, int);
+void  putpair(char *, apr_sdbm_datum_t, apr_sdbm_datum_t, int);
+apr_sdbm_datum_t getpair(char *, apr_sdbm_datum_t, int);
+int  delpair(char *, apr_sdbm_datum_t, int);
+int  chkpage (char *, int);
+apr_sdbm_datum_t getnkey(char *, int, int);
+void splpage(char *, char *, char *, long, int);
+int duppair(char *, apr_sdbm_datum_t, int);
 
 #endif /* SDBM_PAIR_H */
 
Index: dbm/sdbm/sdbm_private.h
===================================================================
RCS file: /home/cvs/apr-util/dbm/sdbm/sdbm_private.h,v
retrieving revision 1.10
diff -u -r1.10 sdbm_private.h
--- dbm/sdbm/sdbm_private.h     1 Jan 2003 00:02:19 -0000       1.10
+++ dbm/sdbm/sdbm_private.h     16 Oct 2003 17:19:20 -0000
@@ -66,17 +66,7 @@
 #include "apr_file_io.h"
 #include "apr_errno.h" /* for apr_status_t */
 
-#if 0
-/* if the block/page size is increased, it breaks perl apr_sdbm_t 
compatibility */
-#define DBLKSIZ 16384
-#define PBLKSIZ 8192
-#define PAIRMAX 8008                   /* arbitrary on PBLKSIZ-N */
-#else
-#define DBLKSIZ 4096
-#define PBLKSIZ 1024
-#define PAIRMAX 1008                   /* arbitrary on PBLKSIZ-N */
-#endif
-#define SPLTMAX        10                      /* maximum allowed splits */
+#define SPLTMAX        10                     /* maximum allowed splits */
 
 /* for apr_sdbm_t.flags */
 #define SDBM_RDONLY            0x1    /* data base open read-only */
@@ -96,9 +86,13 @@
     int  keyptr;                      /* current key for nextkey */
     long blkno;                               /* current page to read/write */
     long pagbno;                      /* current page in pagbuf */
-    char pagbuf[PBLKSIZ];             /* page file block buffer */
+    int  pblksiz;                      /* sdbm's data blocksize (d:1024) */
+    char *pagbuf;                     /* page file block buffer */
+    char *pagtmp;                     /* page file temp workspace */
+    char *pagwrk;                     /* page file split workspace */
     long dirbno;                      /* current block in dirbuf */
-    char dirbuf[DBLKSIZ];             /* directory file block buffer */
+    int  dblksiz;                      /* sdbm's dir blocksize (d:4096) */
+    char *dirbuf;                     /* directory file block buffer */
     int  lckcnt;                       /* number of calls to sdbm_lock */
 };
 


Reply via email to