Update from db-2.3.12.
authordrepper <drepper>
Tue, 11 Nov 1997 20:39:54 +0000 (20:39 +0000)
committerdrepper <drepper>
Tue, 11 Nov 1997 20:39:54 +0000 (20:39 +0000)
93 files changed:
db2/Makefile
db2/btree/bt_cursor.c
db2/btree/bt_delete.c
db2/btree/bt_open.c
db2/btree/bt_put.c
db2/btree/bt_rec.c
db2/btree/bt_recno.c
db2/btree/bt_search.c
db2/btree/bt_split.c
db2/btree/bt_stat.c
db2/btree/btree.src
db2/btree/btree_auto.c
db2/common/db_appinit.c
db2/common/db_apprec.c
db2/common/db_byteorder.c
db2/common/db_region.c
db2/db.h
db2/db/db.c
db2/db/db.src
db2/db/db_auto.c
db2/db/db_dispatch.c
db2/db/db_dup.c
db2/db/db_overflow.c
db2/db/db_pr.c
db2/db/db_rec.c
db2/db/db_ret.c
db2/db/db_thread.c
db2/db185/db185.c
db2/db_int.h
db2/hash/hash.c
db2/hash/hash.src
db2/hash/hash_auto.c
db2/hash/hash_dup.c
db2/hash/hash_page.c
db2/hash/hash_rec.c
db2/include/btree_auto.h
db2/include/btree_ext.h
db2/include/clib_ext.h
db2/include/common_ext.h
db2/include/db.h.src
db2/include/db_am.h
db2/include/db_auto.h
db2/include/db_cxx.h
db2/include/db_ext.h
db2/include/db_int.h.src
db2/include/hash.h
db2/include/hash_auto.h
db2/include/hash_ext.h
db2/include/lock.h
db2/include/lock_ext.h
db2/include/log.h
db2/include/log_ext.h
db2/include/mp.h
db2/include/mp_ext.h
db2/include/mutex_ext.h
db2/include/os_ext.h
db2/include/os_func.h [new file with mode: 0644]
db2/include/txn.h
db2/include/txn_ext.h
db2/lock/lock.c
db2/lock/lock_deadlock.c
db2/log/log.c
db2/log/log_archive.c
db2/log/log_auto.c
db2/log/log_findckp.c
db2/log/log_get.c
db2/log/log_put.c
db2/log/log_rec.c
db2/log/log_register.c
db2/mp/mp_bh.c
db2/mp/mp_fget.c
db2/mp/mp_fopen.c
db2/mp/mp_fput.c
db2/mp/mp_fset.c
db2/mp/mp_open.c
db2/mp/mp_pr.c
db2/mp/mp_region.c
db2/mp/mp_sync.c
db2/mutex/mutex.c
db2/os/os_abs.c [new file with mode: 0644]
db2/os/os_dir.c [new file with mode: 0644]
db2/os/os_fid.c [new file with mode: 0644]
db2/os/os_fsync.c [new file with mode: 0644]
db2/os/os_func.c [new file with mode: 0644]
db2/os/os_map.c [new file with mode: 0644]
db2/os/os_oflags.c [new file with mode: 0644]
db2/os/os_open.c [new file with mode: 0644]
db2/os/os_rpath.c [new file with mode: 0644]
db2/os/os_rw.c [new file with mode: 0644]
db2/os/os_seek.c [new file with mode: 0644]
db2/os/os_sleep.c [new file with mode: 0644]
db2/os/os_stat.c [new file with mode: 0644]
db2/os/os_unlink.c [new file with mode: 0644]

index e6b35aa..8e5cea7 100644 (file)
@@ -58,8 +58,8 @@ libdb-routines := bt_close bt_compare bt_conv bt_cursor bt_delete \
        bt_split bt_stat btree_auto db db_appinit db_apprec \
        db_auto \
        db_byteorder db_conv db_dispatch db_dup db_err db_log2 \
-       db_os_abs db_os_dir db_os_fid db_os_lseek db_os_mmap \
-       db_os_open db_os_rw db_os_sleep db_os_stat db_os_unlink \
+       os_abs os_dir os_fid os_fsync os_func os_map os_oflags \
+       os_open os_rpath os_rw os_seek os_sleep os_stat os_unlink \
        db_overflow db_pr db_rec db_region db_ret db_salloc \
        db_shash db_thread hash hash_auto hash_conv hash_debug \
        hash_dup hash_func hash_page hash_rec hash_stat lock \
index a1266bc..e5f3fae 100644 (file)
@@ -8,7 +8,7 @@
 #include "config.h"
 
 #ifndef lint
-static const char sccsid[] = "@(#)bt_cursor.c  10.33 (Sleepycat) 9/24/97";
+static const char sccsid[] = "@(#)bt_cursor.c  10.35 (Sleepycat) 10/25/97";
 #endif /* not lint */
 
 #ifndef NO_SYSTEM_INCLUDES
@@ -62,10 +62,10 @@ __bam_cursor(dbp, txn, dbcp)
 
        DEBUG_LWRITE(dbp, txn, "bam_cursor", NULL, NULL, 0);
 
-       if ((dbc = (DBC *)calloc(1, sizeof(DBC))) == NULL)
+       if ((dbc = (DBC *)__db_calloc(1, sizeof(DBC))) == NULL)
                return (ENOMEM);
-       if ((cp = (CURSOR *)calloc(1, sizeof(CURSOR))) == NULL) {
-               free(dbc);
+       if ((cp = (CURSOR *)__db_calloc(1, sizeof(CURSOR))) == NULL) {
+               __db_free(dbc);
                return (ENOMEM);
        }
 
@@ -474,7 +474,7 @@ __bam_c_rget(dbp, cp, key, data, flags)
        __bam_stkrel(dbp);
 
 err:   (void)memp_fput(dbp->mpf, cp->page, 0);
-       free(dbt.data);
+       __db_free(dbt.data);
        return (ret);
 }
 
@@ -1422,7 +1422,7 @@ __bam_c_physdel(dbp, cp, h)
        DB_LOCK lock;
        db_indx_t indx;
        db_pgno_t pgno, next_pgno, prev_pgno;
-       int local, ret;
+       int local, normal, ret;
 
        t = dbp->internal;
        ret = 0;
@@ -1457,51 +1457,65 @@ __bam_c_physdel(dbp, cp, h)
                local = 0;
 
        /*
-        * If we're deleting a duplicate entry, call the common code to do
-        * the work.
+        * If we're deleting a duplicate entry and there are other duplicate
+        * entries remaining, call the common code to do the work and fix up
+        * the parent page as necessary.  Otherwise, do a normal btree delete.
+        *
+        * There are 5 possible cases:
+        *
+        * 1. It's not a duplicate item: do a normal btree delete.
+        * 2. It's a duplicate item:
+        *      2a: We delete an item from a page of duplicates, but there are
+        *          more items on the page.
+        *      2b: We delete the last item from a page of duplicates, deleting
+        *          the last duplicate.
+        *      2c: We delete the last item from a page of duplicates, but there
+        *          is a previous page of duplicates.
+        *      2d: We delete the last item from a page of duplicates, but there
+        *          is a following page of duplicates.
+        *
+        * In the case of:
+        *
+        *  1: There's nothing further to do.
+        * 2a: There's nothing further to do.
+        * 2b: Do the normal btree delete instead of a duplicate delete, as
+        *     that deletes both the duplicate chain and the parent page's
+        *     entry.
+        * 2c: There's nothing further to do.
+        * 2d: Delete the duplicate, and update the parent page's entry.
         */
        if (TYPE(h) == P_DUPLICATE) {
                pgno = PGNO(h);
                prev_pgno = PREV_PGNO(h);
                next_pgno = NEXT_PGNO(h);
-               if ((ret = __db_drem(dbp, &h, indx, __bam_free)) != 0)
-                       goto err;
 
-               /*
-                * There are 4 cases:
-                *
-                * 1. We removed an item on a page, but there are more items
-                *    on the page.
-                * 2. We removed the last item on a page, removing the last
-                *    duplicate.
-                * 3. We removed the last item on a page, but there is a
-                *    following page of duplicates.
-                * 4. We removed the last item on a page, but there is a
-                *    previous page of duplicates.
-                *
-                * In case 1, h != NULL, h->pgno == pgno
-                * In case 2, h == NULL,
-                *    prev_pgno == PGNO_INVALID, next_pgno == PGNO_INVALID
-                * In case 3, h != NULL, next_pgno != PGNO_INVALID
-                * In case 4, h == NULL, prev_pgno != PGNO_INVALID
-                *
-                * In case 1, there's nothing else to do.
-                * In case 2, remove the entry from the parent page.
-                * In case 3 or 4, if the deleted page was the first in a chain
-                *    of duplicate pages, update the parent page's entry.
-                *
-                * Test:
-                *      If there were previous pages of duplicates or we didn't
-                *      empty the current page of duplicates, we don't need to
-                *      touch the parent page.
-                */
-               if (prev_pgno != PGNO_INVALID || (h != NULL && pgno == h->pgno))
-                       goto done;
+               if (NUM_ENT(h) == 1 &&
+                   prev_pgno == PGNO_INVALID && next_pgno == PGNO_INVALID)
+                       normal = 1;
+               else {
+                       normal = 0;
 
-               /*
-                * Release any page we're holding and the lock on the deleted
-                * page.
-                */
+                       /* Delete the duplicate. */
+                       if ((ret = __db_drem(dbp, &h, indx, __bam_free)) != 0)
+                               goto err;
+
+                       /*
+                        * 2a: h != NULL, h->pgno == pgno
+                        * 2b: We don't reach this clause, as the above test
+                        *     was true.
+                        * 2c: h == NULL, prev_pgno != PGNO_INVALID
+                        * 2d: h != NULL, next_pgno != PGNO_INVALID
+                        *
+                        * Test for 2a and 2c: if we didn't empty the current
+                        * page or there was a previous page of duplicates, we
+                        * don't need to touch the parent page.
+                        */
+                       if ((h != NULL && pgno == h->pgno) ||
+                           prev_pgno != PGNO_INVALID)
+                               goto done;
+               }
+
+               /* Release any page we're holding and its lock. */
                if (local) {
                        if (h != NULL)
                                (void)memp_fput(dbp->mpf, h, 0);
@@ -1519,37 +1533,33 @@ __bam_c_physdel(dbp, cp, h)
                }
                local = 1;
 
-               /*
-                * If we deleted the last duplicate, we can fall out and do a
-                * normal btree delete in the context of the parent page.  If
-                * not, we have to update the parent's page.
-                */
+               /* Switch to the parent page's entry. */
                indx = cp->indx;
-               if (next_pgno != PGNO_INVALID) {
-                       /*
-                        * Copy, delete, update and re-insert the parent page's
-                        * entry.
-                        */
-                       bo = *GET_BOVERFLOW(h, indx);
-                       (void)__db_ditem(dbp, h, indx, BOVERFLOW_SIZE);
-                       bo.pgno = next_pgno;
-                       memset(&dbt, 0, sizeof(dbt));
-                       dbt.data = &bo;
-                       dbt.size = BOVERFLOW_SIZE;
-                       (void)__db_pitem(dbp,
-                           h, indx, BOVERFLOW_SIZE, &dbt, NULL);
-
-                       /* Discard the parent page. */
-                       (void)memp_fput(dbp->mpf, h, 0);
-                       (void)__BT_TLPUT(dbp, lock);
-                       local = 0;
+               if (normal)
+                       goto btd;
 
-                       goto done;
-               }
+               /*
+                * Copy, delete, update, add-back the parent page's data entry.
+                *
+                * XXX
+                * This may be a performance/logging problem.  We should add a
+                * log message which simply logs/updates a random set of bytes
+                * on a page, and use it instead of doing a delete/add pair.
+                */
+               indx += O_INDX;
+               bo = *GET_BOVERFLOW(h, indx);
+               (void)__db_ditem(dbp, h, indx, BOVERFLOW_SIZE);
+               bo.pgno = next_pgno;
+               memset(&dbt, 0, sizeof(dbt));
+               dbt.data = &bo;
+               dbt.size = BOVERFLOW_SIZE;
+               (void)__db_pitem(dbp, h, indx, BOVERFLOW_SIZE, &dbt, NULL);
+               (void)memp_fset(dbp->mpf, h, DB_MPOOL_DIRTY);
+               goto done;
        }
 
        /* Otherwise, do a normal btree delete. */
-       if ((ret = __bam_ditem(dbp, h, indx)) != 0)
+btd:   if ((ret = __bam_ditem(dbp, h, indx)) != 0)
                goto err;
        if ((ret = __bam_ditem(dbp, h, indx)) != 0)
                goto err;
@@ -1584,7 +1594,7 @@ __bam_c_physdel(dbp, cp, h)
                }
 
                ret = __bam_dpage(dbp, &dbt);
-               free(dbt.data);
+               __db_free(dbt.data);
        }
 
 err:
index 9892954..9593d01 100644 (file)
@@ -47,7 +47,7 @@
 #include "config.h"
 
 #ifndef lint
-static const char sccsid[] = "@(#)bt_delete.c  10.21 (Sleepycat) 9/3/97";
+static const char sccsid[] = "@(#)bt_delete.c  10.22 (Sleepycat) 11/2/97";
 #endif /* not lint */
 
 #ifndef NO_SYSTEM_INCLUDES
@@ -266,9 +266,10 @@ __bam_ditem(dbp, h, indx)
                case B_DUPLICATE:
                case B_OVERFLOW:
                        nbytes = BINTERNAL_SIZE(bi->len);
+                       bo = (BOVERFLOW *)bi->data;
                        goto offpage;
                case B_KEYDATA:
-                       nbytes = BKEYDATA_SIZE(bi->len);
+                       nbytes = BINTERNAL_SIZE(bi->len);
                        break;
                default:
                        return (__db_pgfmt(dbp, h->pgno));
@@ -289,7 +290,7 @@ __bam_ditem(dbp, h, indx)
                        if (indx > 0 && h->inp[indx] == h->inp[indx - P_INDX])
                                return (__bam_adjindx(dbp,
                                    h, indx, indx - P_INDX, 0));
-                       if (indx < (u_int32_t)(NUM_ENT(h) - P_INDX) &&
+                       if (indx + P_INDX < (u_int32_t)NUM_ENT(h) &&
                            h->inp[indx] == h->inp[indx + P_INDX])
                                return (__bam_adjindx(dbp,
                                    h, indx, indx + O_INDX, 0));
@@ -301,9 +302,9 @@ __bam_ditem(dbp, h, indx)
                case B_DUPLICATE:
                case B_OVERFLOW:
                        nbytes = BOVERFLOW_SIZE;
+                       bo = GET_BOVERFLOW(h, indx);
 
 offpage:               /* Delete duplicate/offpage chains. */
-                       bo = GET_BOVERFLOW(h, indx);
                        if (B_TYPE(bo->type) == B_DUPLICATE) {
                                if ((ret =
                                    __db_ddup(dbp, bo->pgno, __bam_free)) != 0)
@@ -523,7 +524,7 @@ __bam_dpages(dbp, t)
 
        /*
         * If we deleted the next-to-last item from the root page, the tree
-        * has collapsed a level.  Try and write lock the remaining root + 1
+        * can collapse a level.  Try and write lock the remaining root + 1
         * page and copy it onto the root page.  If we can't get the lock,
         * that's okay, the tree just stays a level deeper than we'd like.
         */
@@ -546,8 +547,8 @@ __bam_dpages(dbp, t)
                        b.data = P_ENTRY(epg->page, 0);
                        b.size = BINTERNAL_SIZE(((BINTERNAL *)b.data)->len);
                        __bam_rsplit_log(dbp->dbenv->lg_info, dbp->txn,
-                          &h->lsn, 0, dbp->log_fileid, h->pgno, &a, &b,
-                          &epg->page->lsn);
+                          &h->lsn, 0, dbp->log_fileid, h->pgno, &a,
+                          RE_NREC(epg->page), &b, &epg->page->lsn);
                }
 
                /*
@@ -565,15 +566,19 @@ __bam_dpages(dbp, t)
                if (TYPE(h) == P_IRECNO ||
                    (TYPE(h) == P_IBTREE && F_ISSET(dbp, DB_BT_RECNUM)))
                        RE_NREC_SET(epg->page, rcnt);
+               (void)memp_fset(dbp->mpf, epg->page, DB_MPOOL_DIRTY);
 
-               /* Free the last page in that level of the btree. */
-               ++t->lstat.bt_freed;
+               /*
+                * Free the last page in that level of the btree and discard
+                * the lock.  (The call to __bam_free discards our reference
+                * to the page.)
+                */
                (void)__bam_free(dbp, h);
+               (void)__BT_TLPUT(dbp, lock);
+               ++t->lstat.bt_freed;
 
                /* Adjust the cursors. */
                __bam_ca_move(dbp, t, h->pgno, PGNO_ROOT);
-
-               (void)__BT_TLPUT(dbp, lock);
        }
 
        /* Release the top page in the subtree. */
index 354888c..2361f69 100644 (file)
@@ -47,7 +47,7 @@
 #include "config.h"
 
 #ifndef lint
-static const char sccsid[] = "@(#)bt_open.c    10.20 (Sleepycat) 8/19/97";
+static const char sccsid[] = "@(#)bt_open.c    10.21 (Sleepycat) 10/25/97";
 #endif /* not lint */
 
 /*
@@ -95,7 +95,7 @@ __bam_open(dbp, type, dbinfo)
        int ret;
 
        /* Allocate the btree internal structure. */
-       if ((t = (BTREE *)calloc(1, sizeof(BTREE))) == NULL)
+       if ((t = (BTREE *)__db_calloc(1, sizeof(BTREE))) == NULL)
                return (ENOMEM);
 
        t->bt_sp = t->bt_csp = t->bt_stack;
@@ -179,7 +179,7 @@ einval:     ret = EINVAL;
 err:   if (t != NULL) {
                /* If we allocated room for key/data return, discard it. */
                if (t->bt_rkey.data != NULL)
-                       free(t->bt_rkey.data);
+                       __db_free(t->bt_rkey.data);
 
                FREE(t, sizeof(BTREE));
        }
@@ -201,7 +201,7 @@ __bam_bdup(orig, new)
 
        ot = orig->internal;
 
-       if ((t = (BTREE *)calloc(1, sizeof(*t))) == NULL)
+       if ((t = (BTREE *)__db_calloc(1, sizeof(*t))) == NULL)
                return (ENOMEM);
 
        /*
@@ -248,7 +248,7 @@ __bam_keyalloc(t)
         * Recno keys are always the same size, and we don't want to have
         * to check for space on each return.  Allocate it now.
         */
-       if ((t->bt_rkey.data = (void *)malloc(sizeof(db_recno_t))) == NULL)
+       if ((t->bt_rkey.data = (void *)__db_malloc(sizeof(db_recno_t))) == NULL)
                return (ENOMEM);
        t->bt_rkey.ulen = sizeof(db_recno_t);
        return (0);
index af09f76..b3d775b 100644 (file)
@@ -47,7 +47,7 @@
 #include "config.h"
 
 #ifndef lint
-static const char sccsid[] = "@(#)bt_put.c     10.25 (Sleepycat) 9/17/97";
+static const char sccsid[] = "@(#)bt_put.c     10.31 (Sleepycat) 10/26/97";
 #endif /* not lint */
 
 #ifndef NO_SYSTEM_INCLUDES
@@ -66,7 +66,10 @@ static const char sccsid[] = "@(#)bt_put.c   10.25 (Sleepycat) 9/17/97";
 static int __bam_fixed __P((BTREE *, DBT *));
 static int __bam_lookup __P((DB *, DBT *, int *));
 static int __bam_ndup __P((DB *, PAGE *, u_int32_t));
-static int __bam_partial __P((DB *, DBT *, PAGE *, u_int32_t));
+static int __bam_ovput __P((DB *, PAGE *, u_int32_t, DBT *));
+static int __bam_partial __P((DB *, DBT *, PAGE *, u_int32_t, u_int32_t));
+static u_int32_t
+          __bam_partsize __P((DB *, DBT *, PAGE *, u_int32_t));
 
 /*
  * __bam_put --
@@ -334,21 +337,6 @@ slow:      return (__bam_search(dbp, key, S_INSERT, 1, NULL, exactp));
 }
 
 /*
- * OVPUT --
- *     Copy an overflow item onto a page.
- */
-#undef OVPUT
-#define        OVPUT(h, indx, bo) do {                                         \
-       DBT __hdr;                                                      \
-       memset(&__hdr, 0, sizeof(__hdr));                               \
-       __hdr.data = &bo;                                               \
-       __hdr.size = BOVERFLOW_SIZE;                                    \
-       if ((ret = __db_pitem(dbp,                                      \
-           h, indx, BOVERFLOW_SIZE, &__hdr, NULL)) != 0)               \
-               return (ret);                                           \
-} while (0)
-
-/*
  * __bam_iitem --
  *     Insert an item into the tree.
  *
@@ -365,19 +353,18 @@ __bam_iitem(dbp, hp, indxp, key, data, op, flags)
 {
        BTREE *t;
        BKEYDATA *bk;
-       BOVERFLOW kbo, dbo;
        DBT tdbt;
        PAGE *h;
        db_indx_t indx;
-       u_int32_t have_bytes, need_bytes, needed;
-       int bigkey, bigdata, dcopy, dupadjust, ret;
+       u_int32_t data_size, have_bytes, need_bytes, needed;
+       int bigkey, bigdata, dupadjust, replace, ret;
 
        t = dbp->internal;
        h = *hp;
        indx = *indxp;
 
-       dupadjust = 0;
        bk = NULL;                      /* XXX: Shut the compiler up. */
+       dupadjust = replace = 0;
 
        /*
         * If it's a page of duplicates, call the common code to do the work.
@@ -385,7 +372,7 @@ __bam_iitem(dbp, hp, indxp, key, data, op, flags)
         * !!!
         * Here's where the hp and indxp are important.  The duplicate code
         * may decide to rework/rearrange the pages and indices we're using,
-        * so the caller must understand that the stack has to change.
+        * so the caller must understand that the page stack may change.
         */
        if (TYPE(h) == P_DUPLICATE) {
                /* Adjust the index for the new item if it's a DB_AFTER op. */
@@ -401,24 +388,7 @@ __bam_iitem(dbp, hp, indxp, key, data, op, flags)
                return (__db_dput(dbp, data, hp, indxp, __bam_new));
        }
 
-       /*
-        * XXX
-        * Handle partial puts.
-        *
-        * This is truly awful from a performance standput.  We don't optimize
-        * for partial puts at all, we delete the record and add it back in,
-        * regardless of size or if we're simply overwriting current data.
-        * The hash access method does this a lot better than we do, and we're
-        * eventually going to have to fix it.
-        */
-       if (F_ISSET(data, DB_DBT_PARTIAL)) {
-               tdbt = *data;
-               if ((ret = __bam_partial(dbp, &tdbt, h, indx)) != 0)
-                       return (ret);
-               data = &tdbt;
-       }
-
-       /* If it's a short fixed-length record, fix it up. */
+       /* Handle fixed-length records: build the real record. */
        if (F_ISSET(dbp, DB_RE_FIXEDLEN) && data->size != t->bt_recno->re_len) {
                tdbt = *data;
                if ((ret = __bam_fixed(t, &tdbt)) != 0)
@@ -427,30 +397,15 @@ __bam_iitem(dbp, hp, indxp, key, data, op, flags)
        }
 
        /*
-        * If the key or data item won't fit on a page, store it in the
-        * overflow pages.
-        *
-        * !!!
-        * From this point on, we have to recover the allocated overflow
-        * pages on error.
+        * Figure out how much space the data will take, including if it's a
+        * partial record.  If either of the key or data items won't fit on
+        * a page, we'll have to store them on overflow pages.
         */
-       bigkey = bigdata = 0;
-       if (LF_ISSET(BI_NEWKEY) && key->size > t->bt_ovflsize) {
-               B_TSET(kbo.type, B_OVERFLOW, 0);
-               kbo.tlen = key->size;
-               if ((ret = __db_poff(dbp, key, &kbo.pgno, __bam_new)) != 0)
-                       goto err;
-               bigkey = 1;
-       }
-       if (data->size > t->bt_ovflsize) {
-               B_TSET(dbo.type, B_OVERFLOW, 0);
-               dbo.tlen = data->size;
-               if ((ret = __db_poff(dbp, data, &dbo.pgno, __bam_new)) != 0)
-                       goto err;
-               bigdata = 1;
-       }
+       bigkey = LF_ISSET(BI_NEWKEY) && key->size > t->bt_ovflsize;
+       data_size = F_ISSET(data, DB_DBT_PARTIAL) ?
+           __bam_partsize(dbp, data, h, indx) : data->size;
+       bigdata = data_size > t->bt_ovflsize;
 
-       dcopy = 0;
        needed = 0;
        if (LF_ISSET(BI_NEWKEY)) {
                /* If BI_NEWKEY is set we're adding a new key and data pair. */
@@ -461,7 +416,7 @@ __bam_iitem(dbp, hp, indxp, key, data, op, flags)
                if (bigdata)
                        needed += BOVERFLOW_PSIZE;
                else
-                       needed += BKEYDATA_PSIZE(data->size);
+                       needed += BKEYDATA_PSIZE(data_size);
        } else {
                /*
                 * We're either overwriting the data item of a key/data pair
@@ -482,16 +437,8 @@ __bam_iitem(dbp, hp, indxp, key, data, op, flags)
                if (bigdata)
                        need_bytes += BOVERFLOW_PSIZE;
                else
-                       need_bytes += BKEYDATA_PSIZE(data->size);
+                       need_bytes += BKEYDATA_PSIZE(data_size);
 
-               /*
-                * If we're overwriting a data item, we copy it if it's not a
-                * special record type and it's the same size (including any
-                * alignment) and do a delete/insert otherwise.
-                */
-               if (op == DB_CURRENT && !bigdata &&
-                   B_TYPE(bk->type) == B_KEYDATA && have_bytes == need_bytes)
-                       dcopy = 1;
                if (have_bytes < need_bytes)
                        needed += need_bytes - have_bytes;
        }
@@ -505,9 +452,15 @@ __bam_iitem(dbp, hp, indxp, key, data, op, flags)
         * check in the btree split code, so we don't undo it there!?!?
         */
        if (P_FREESPACE(h) < needed ||
-           (t->bt_maxkey != 0 && NUM_ENT(h) > t->bt_maxkey)) {
-               ret = DB_NEEDSPLIT;
-               goto err;
+           (t->bt_maxkey != 0 && NUM_ENT(h) > t->bt_maxkey))
+               return (DB_NEEDSPLIT);
+
+       /* Handle partial puts: build the real record. */
+       if (F_ISSET(data, DB_DBT_PARTIAL)) {
+               tdbt = *data;
+               if ((ret = __bam_partial(dbp, &tdbt, h, indx, data_size)) != 0)
+                       return (ret);
+               data = &tdbt;
        }
 
        /*
@@ -515,10 +468,10 @@ __bam_iitem(dbp, hp, indxp, key, data, op, flags)
         *
         * 1. Append a new key/data pair.
         * 2. Insert a new key/data pair.
-        * 3. Copy the data item.
-        * 4. Delete/insert the data item.
-        * 5. Append a new data item.
-        * 6. Insert a new data item.
+        * 3. Append a new data item (a new duplicate).
+        * 4. Insert a new data item (a new duplicate).
+        * 5. Overflow item: delete and re-add the data item.
+        * 6. Replace the data item.
         */
        if (LF_ISSET(BI_NEWKEY)) {
                switch (op) {
@@ -533,42 +486,17 @@ __bam_iitem(dbp, hp, indxp, key, data, op, flags)
                }
 
                /* Add the key. */
-               if (bigkey)
-                       OVPUT(h, indx, kbo);
-               else {
-                       DBT __data;
-                       memset(&__data, 0, sizeof(__data));
-                       __data.data = key->data;
-                       __data.size = key->size;
+               if (bigkey) {
+                       if ((ret = __bam_ovput(dbp, h, indx, key)) != 0)
+                               return (ret);
+               } else
                        if ((ret = __db_pitem(dbp, h, indx,
-                           BKEYDATA_SIZE(key->size), NULL, &__data)) != 0)
-                               goto err;
-               }
+                           BKEYDATA_SIZE(key->size), NULL, key)) != 0)
+                               return (ret);
                ++indx;
        } else {
                switch (op) {
-               case DB_CURRENT:        /* 3. Copy the data item. */
-                       /*
-                        * If we're not logging and it's possible, overwrite
-                        * the current item.
-                        *
-                        * XXX
-                        * We should add a separate logging message so that
-                        * we can do this anytime it's possible, including
-                        * for partial record puts.
-                        */
-                       if (dcopy && !DB_LOGGING(dbp)) {
-                               bk->len = data->size;
-                               memcpy(bk->data, data->data, data->size);
-                               goto done;
-                       }
-                                       /* 4. Delete/insert the data item. */
-                       if (TYPE(h) == P_LBTREE)
-                               ++indx;
-                       if ((ret = __bam_ditem(dbp, h, indx)) != 0)
-                               goto err;
-                       break;
-               case DB_AFTER:          /* 5. Append a new data item. */
+               case DB_AFTER:          /* 3. Append a new data item. */
                        if (TYPE(h) == P_LBTREE) {
                                /*
                                 * Adjust the cursor and copy in the key for
@@ -576,7 +504,7 @@ __bam_iitem(dbp, hp, indxp, key, data, op, flags)
                                 */
                                if ((ret = __bam_adjindx(dbp,
                                    h, indx + P_INDX, indx, 1)) != 0)
-                                       goto err;
+                                       return (ret);
 
                                indx += 3;
                                dupadjust = 1;
@@ -589,7 +517,7 @@ __bam_iitem(dbp, hp, indxp, key, data, op, flags)
                                *indxp += 1;
                        }
                        break;
-               case DB_BEFORE:         /* 6. Insert a new data item. */
+               case DB_BEFORE:         /* 4. Insert a new data item. */
                        if (TYPE(h) == P_LBTREE) {
                                /*
                                 * Adjust the cursor and copy in the key for
@@ -597,43 +525,62 @@ __bam_iitem(dbp, hp, indxp, key, data, op, flags)
                                 */
                                if ((ret =
                                    __bam_adjindx(dbp, h, indx, indx, 1)) != 0)
-                                       goto err;
+                                       return (ret);
 
                                ++indx;
                                dupadjust = 1;
                        } else
                                __bam_ca_di(dbp, h->pgno, indx, 1);
                        break;
+               case DB_CURRENT:
+                       if (TYPE(h) == P_LBTREE)
+                               ++indx;
+
+                       /*
+                        * 5. Delete/re-add the data item.
+                        *
+                        * If we're dealing with offpage items, we have to 
+                        * delete and then re-add the item.
+                        */
+                       if (bigdata || B_TYPE(bk->type) == B_OVERFLOW) {
+                               if ((ret = __bam_ditem(dbp, h, indx)) != 0)
+                                       return (ret);
+                               break;
+                       }
+
+                       /* 6. Replace the data item. */
+                       replace = 1;
+                       break;
                default:
                        abort();
                }
        }
 
        /* Add the data. */
-       if (bigdata)
-               OVPUT(h, indx, dbo);
-       else {
+       if (bigdata) {
+               if ((ret = __bam_ovput(dbp, h, indx, data)) != 0)
+                       return (ret);
+       } else {
                BKEYDATA __bk;
-               DBT __hdr, __data;
-               memset(&__data, 0, sizeof(__data));
-               __data.data = data->data;
-               __data.size = data->size;
+               DBT __hdr;
 
                if (LF_ISSET(BI_DELETED)) {
                        B_TSET(__bk.type, B_KEYDATA, 1);
-                       __bk.len = __data.size;
+                       __bk.len = data->size;
                        __hdr.data = &__bk;
                        __hdr.size = SSZA(BKEYDATA, data);
                        ret = __db_pitem(dbp, h, indx,
-                           BKEYDATA_SIZE(__data.size), &__hdr, &__data);
-               } else
+                           BKEYDATA_SIZE(data->size), &__hdr, data);
+               } else if (replace)
+                       ret = __bam_ritem(dbp, h, indx, data);
+               else
                        ret = __db_pitem(dbp, h, indx,
-                           BKEYDATA_SIZE(data->size), NULL, &__data);
+                           BKEYDATA_SIZE(data->size), NULL, data);
                if (ret != 0)
-                       goto err;
+                       return (ret);
        }
 
-done:  ++t->lstat.bt_added;
+       ++t->lstat.bt_added;
 
        ret = memp_fset(dbp->mpf, h, DB_MPOOL_DIRTY);
 
@@ -645,22 +592,206 @@ done:    ++t->lstat.bt_added;
        if (dupadjust && P_FREESPACE(h) <= dbp->pgsize / 2) {
                --indx;
                if ((ret = __bam_ndup(dbp, h, indx)) != 0)
-                       goto err;
+                       return (ret);
        }
 
        if (t->bt_recno != NULL)
                F_SET(t->bt_recno, RECNO_MODIFIED);
 
-       if (0) {
-err:           if (bigkey)
-                       (void)__db_doff(dbp, kbo.pgno, __bam_free);
-               if (bigdata)
-                       (void)__db_doff(dbp, dbo.pgno, __bam_free);
-       }
        return (ret);
 }
 
 /*
+ * __bam_partsize --
+ *     Figure out how much space a partial data item is in total.
+ */
+static u_int32_t
+__bam_partsize(dbp, data, h, indx)
+       DB *dbp;
+       DBT *data;
+       PAGE *h;
+       u_int32_t indx;
+{
+       BKEYDATA *bk;
+       u_int32_t nbytes;
+
+       /*
+        * Figure out how much total space we'll need.  If the record doesn't
+        * already exist, it's simply the data we're provided.
+        */
+       if (indx >= NUM_ENT(h))
+               return (data->doff + data->size);
+
+       /*
+        * Otherwise, it's the data provided plus any already existing data
+        * that we're not replacing.
+        */
+       bk = GET_BKEYDATA(h, indx + (TYPE(h) == P_LBTREE ? O_INDX : 0));
+       nbytes =
+           B_TYPE(bk->type) == B_OVERFLOW ? ((BOVERFLOW *)bk)->tlen : bk->len;
+
+       /*
+        * There are really two cases here:
+        *
+        * Case 1: We are replacing some bytes that do not exist (i.e., they
+        * are past the end of the record).  In this case the number of bytes
+        * we are replacing is irrelevant and all we care about is how many
+        * bytes we are going to add from offset.  So, the new record length
+        * is going to be the size of the new bytes (size) plus wherever those
+        * new bytes begin (doff).
+        *
+        * Case 2: All the bytes we are replacing exist.  Therefore, the new
+        * size is the oldsize (nbytes) minus the bytes we are replacing (dlen)
+        * plus the bytes we are adding (size).
+        */
+       if (nbytes < data->doff + data->dlen)           /* Case 1 */
+               return (data->doff + data->size);
+
+       return (nbytes + data->size - data->dlen);      /* Case 2 */
+}
+
+/*
+ * OVPUT --
+ *     Copy an overflow item onto a page.
+ */
+#undef OVPUT
+#define        OVPUT(h, indx, bo) do {                                         \
+       DBT __hdr;                                                      \
+       memset(&__hdr, 0, sizeof(__hdr));                               \
+       __hdr.data = &bo;                                               \
+       __hdr.size = BOVERFLOW_SIZE;                                    \
+       if ((ret = __db_pitem(dbp,                                      \
+           h, indx, BOVERFLOW_SIZE, &__hdr, NULL)) != 0)               \
+               return (ret);                                           \
+} while (0)
+
+/*
+ * __bam_ovput --
+ *     Build an overflow item and put it on the page.
+ */
+static int
+__bam_ovput(dbp, h, indx, item)
+       DB *dbp;
+       PAGE *h;
+       u_int32_t indx;
+       DBT *item;
+{
+       BOVERFLOW bo;
+       int ret;
+
+       B_TSET(bo.type, B_OVERFLOW, 0);
+       bo.tlen = item->size;
+       if ((ret = __db_poff(dbp, item, &bo.pgno, __bam_new)) != 0)
+               return (ret);
+
+       OVPUT(h, indx, bo);
+
+       return (0);
+}
+
+/*
+ * __bam_ritem --
+ *     Replace an item on a page.
+ *
+ * PUBLIC: int __bam_ritem __P((DB *, PAGE *, u_int32_t, DBT *));
+ */
+int
+__bam_ritem(dbp, h, indx, data)
+       DB *dbp;
+       PAGE *h;
+       u_int32_t indx;
+       DBT *data;
+{
+       BKEYDATA *bk;
+       DBT orig, repl;
+       db_indx_t lo, ln, min, off, prefix, suffix;
+       int32_t nbytes;
+       int cnt, ret;
+       u_int8_t *p, *t;
+
+       /*
+        * Replace a single item onto a page.  The logic figuring out where
+        * to insert and whether it fits is handled in the caller.  All we do
+        * here is manage the page shuffling.
+        */
+       bk = GET_BKEYDATA(h, indx);
+
+       /* Log the change. */
+       if (DB_LOGGING(dbp)) {
+               /*
+                * We might as well check to see if the two data items share
+                * a common prefix and suffix -- it can save us a lot of log
+                * message if they're large.
+                */
+               min = data->size < bk->len ? data->size : bk->len;
+               for (prefix = 0,
+                   p = bk->data, t = data->data;
+                   prefix < min && *p == *t; ++prefix, ++p, ++t)
+                       ;
+
+               min -= prefix;
+               for (suffix = 0,
+                   p = (u_int8_t *)bk->data + bk->len - 1,
+                   t = (u_int8_t *)data->data + data->size - 1;
+                   suffix < min && *p == *t; ++suffix, --p, --t)
+                       ;
+
+               /* We only log the parts of the keys that have changed. */
+               orig.data = (u_int8_t *)bk->data + prefix;
+               orig.size = bk->len - (prefix + suffix);
+               repl.data = (u_int8_t *)data->data + prefix;
+               repl.size = data->size - (prefix + suffix);
+               if ((ret = __bam_repl_log(dbp->dbenv->lg_info, dbp->txn,
+                   &LSN(h), 0, dbp->log_fileid, PGNO(h), &LSN(h),
+                   (u_int32_t)indx, (u_int32_t)B_DISSET(bk->type),
+                   &orig, &repl, (u_int32_t)prefix, (u_int32_t)suffix)) != 0)
+                       return (ret);
+       }
+
+       /*
+        * Set references to the first in-use byte on the page and the
+        * first byte of the item being replaced.
+        */
+       p = (u_int8_t *)h + HOFFSET(h);
+       t = (u_int8_t *)bk;
+
+       /*
+        * If the entry is growing in size, shift the beginning of the data
+        * part of the page down.  If the entry is shrinking in size, shift
+        * the beginning of the data part of the page up.  Use memmove(3),
+        * the regions overlap.
+        */
+       lo = BKEYDATA_SIZE(bk->len);
+       ln = BKEYDATA_SIZE(data->size);
+       if (lo != ln) {
+               nbytes = lo - ln;               /* Signed difference. */
+               if (p == t)                     /* First index is fast. */
+                       h->inp[indx] += nbytes;
+               else {                          /* Else, shift the page. */
+                       memmove(p + nbytes, p, t - p);
+
+                       /* Adjust the indices' offsets. */
+                       off = h->inp[indx];
+                       for (cnt = 0; cnt < NUM_ENT(h); ++cnt)
+                               if (h->inp[cnt] <= off)
+                                       h->inp[cnt] += nbytes;
+               }
+
+               /* Clean up the page and adjust the item's reference. */
+               HOFFSET(h) += nbytes;
+               t += nbytes;
+       }
+
+       /* Copy the new item onto the page. */
+       bk = (BKEYDATA *)t;
+       B_TSET(bk->type, B_KEYDATA, 0);
+       bk->len = data->size;
+       memcpy(bk->data, data->data, data->size);
+
+       return (0);
+}
+
+/*
  * __bam_ndup --
  *     Check to see if the duplicate set at indx should have its own page.
  *     If it should, create it.
@@ -766,16 +897,21 @@ __bam_fixed(t, dbt)
        rp = t->bt_recno;
 
        /*
-        * If using fixed-length records, and the record is long, return
-        * EINVAL.  If it's short, pad it out.  Use the record data return
-        * memory, it's only short-term.
+        * If database contains fixed-length records, and the record is long,
+        * return EINVAL.
         */
        if (dbt->size > rp->re_len)
                return (EINVAL);
+
+       /*
+        * The caller checked to see if it was just right, so we know it's
+        * short.  Pad it out.  We use the record data return memory, it's
+        * only a short-term use.
+        */
        if (t->bt_rdata.ulen < rp->re_len) {
                t->bt_rdata.data = t->bt_rdata.data == NULL ?
-                   (void *)malloc(rp->re_len) :
-                   (void *)realloc(t->bt_rdata.data, rp->re_len);
+                   (void *)__db_malloc(rp->re_len) :
+                   (void *)__db_realloc(t->bt_rdata.data, rp->re_len);
                if (t->bt_rdata.data == NULL) {
                        t->bt_rdata.ulen = 0;
                        return (ENOMEM);
@@ -786,12 +922,16 @@ __bam_fixed(t, dbt)
        memset((u_int8_t *)t->bt_rdata.data + dbt->size,
            rp->re_pad, rp->re_len - dbt->size);
 
-       /* Set the DBT to reference our new record. */
+       /*
+        * Clean up our flags and other information just in case, and
+        * change the caller's DBT to reference our created record.
+        */
        t->bt_rdata.size = rp->re_len;
        t->bt_rdata.dlen = 0;
        t->bt_rdata.doff = 0;
        t->bt_rdata.flags = 0;
        *dbt = t->bt_rdata;
+
        return (0);
 }
 
@@ -800,47 +940,28 @@ __bam_fixed(t, dbt)
  *     Build the real record for a partial put.
  */
 static int
-__bam_partial(dbp, dbt, h, indx)
+__bam_partial(dbp, dbt, h, indx, nbytes)
        DB *dbp;
        DBT *dbt;
        PAGE *h;
-       u_int32_t indx;
+       u_int32_t indx, nbytes;
 {
        BTREE *t;
        BKEYDATA *bk, tbk;
        BOVERFLOW *bo;
        DBT copy;
-       u_int32_t len, nbytes, tlen;
+       u_int32_t len, tlen;
        int ret;
        u_int8_t *p;
 
        bo = NULL;                      /* XXX: Shut the compiler up. */
        t = dbp->internal;
 
-       /*
-        * Figure out how much total space we'll need.  Worst case is where
-        * the record is 0 bytes long, in which case doff causes the record
-        * to extend, and the put data is appended to it.
-        */
-       if (indx < NUM_ENT(h)) {
-               bk = GET_BKEYDATA(h, indx + (TYPE(h) == P_LBTREE ? O_INDX : 0));
-               if (B_TYPE(bk->type) == B_OVERFLOW) {
-                       bo = (BOVERFLOW *)bk;
-                       nbytes = bo->tlen;
-               } else
-                       nbytes = bk->len;
-       } else {
-               bk = &tbk;
-               B_TSET(bk->type, B_KEYDATA, 0);
-               nbytes = bk->len = 0;
-       }
-       nbytes += dbt->doff + dbt->size + dbt->dlen;
-
-       /* Allocate the space. */
+       /* We use the record data return memory, it's only a short-term use. */
        if (t->bt_rdata.ulen < nbytes) {
                t->bt_rdata.data = t->bt_rdata.data == NULL ?
-                   (void *)malloc(nbytes) :
-                   (void *)realloc(t->bt_rdata.data, nbytes);
+                   (void *)__db_malloc(nbytes) :
+                   (void *)__db_realloc(t->bt_rdata.data, nbytes);
                if (t->bt_rdata.data == NULL) {
                        t->bt_rdata.ulen = 0;
                        return (ENOMEM);
@@ -848,6 +969,16 @@ __bam_partial(dbp, dbt, h, indx)
                t->bt_rdata.ulen = nbytes;
        }
 
+       /* Find the current record. */
+       if (indx < NUM_ENT(h)) {
+               bk = GET_BKEYDATA(h, indx + (TYPE(h) == P_LBTREE ? O_INDX : 0));
+               bo = (BOVERFLOW *)bk;
+       } else {
+               bk = &tbk;
+               B_TSET(bk->type, B_KEYDATA, 0);
+               bk->len = 0;
+       }
+
        /* We use nul bytes for extending the record, get it over with. */
        memset(t->bt_rdata.data, 0, nbytes);
 
index 9aeb395..c0b7c8a 100644 (file)
@@ -8,7 +8,7 @@
 #include "config.h"
 
 #ifndef lint
-static const char sccsid[] = "@(#)bt_rec.c     10.14 (Sleepycat) 9/6/97";
+static const char sccsid[] = "@(#)bt_rec.c     10.17 (Sleepycat) 11/2/97";
 #endif /* not lint */
 
 #ifndef NO_SYSTEM_INCLUDES
@@ -298,8 +298,8 @@ __bam_split_recover(logp, dbtp, lsnp, redo, info)
                        goto done;
 
                /* Allocate and initialize new left/right child pages. */
-               if ((_lp = (PAGE *)malloc(file_dbp->pgsize)) == NULL ||
-                   (_rp = (PAGE *)malloc(file_dbp->pgsize)) == NULL) {
+               if ((_lp = (PAGE *)__db_malloc(file_dbp->pgsize)) == NULL ||
+                   (_rp = (PAGE *)__db_malloc(file_dbp->pgsize)) == NULL) {
                        ret = ENOMEM;
                        __db_err(file_dbp->dbenv, "%s", strerror(ret));
                        goto out;
@@ -490,9 +490,9 @@ out:        /* Free any pages that weren't dirtied. */
 
        /* Free any allocated space. */
        if (_lp != NULL)
-               free(_lp);
+               __db_free(_lp);
        if (_rp != NULL)
-               free(_rp);
+               __db_free(_rp);
 
        REC_CLOSE;
 }
@@ -541,7 +541,8 @@ __bam_rsplit_recover(logp, dbtp, lsnp, redo, info)
        } else if (cmp_n == 0 && !redo) {
                /* Need to undo update described. */
                P_INIT(pagep, file_dbp->pgsize, PGNO_ROOT,
-                   PGNO_INVALID, PGNO_INVALID, pagep->level + 1, TYPE(pagep));
+                   argp->nrec, PGNO_INVALID, pagep->level + 1,
+                   file_dbp->type == DB_BTREE ? P_IBTREE : P_IRECNO);
                if ((ret = __db_pitem(file_dbp, pagep, 0,
                    argp->rootent.size, &argp->rootent, NULL)) != 0)
                        goto out;
@@ -764,3 +765,106 @@ __bam_cdel_recover(logp, dbtp, lsnp, redo, info)
 
 out:   REC_CLOSE;
 }
+
+/*
+ * __bam_repl_recover --
+ *     Recovery function for page item replacement.
+ *
+ * PUBLIC: int __bam_repl_recover
+ * PUBLIC:   __P((DB_LOG *, DBT *, DB_LSN *, int, void *));
+ */
+int
+__bam_repl_recover(logp, dbtp, lsnp, redo, info)
+       DB_LOG *logp;
+       DBT *dbtp;
+       DB_LSN *lsnp;
+       int redo;
+       void *info;
+{
+       __bam_repl_args *argp;
+       BKEYDATA *bk;
+       DB *file_dbp, *mdbp;
+       DBT dbt;
+       DB_MPOOLFILE *mpf;
+       PAGE *pagep;
+       int cmp_n, cmp_p, modified, ret;
+       u_int8_t *p;
+
+       REC_PRINT(__bam_repl_print);
+       REC_INTRO(__bam_repl_read);
+
+       if ((ret = memp_fget(mpf, &argp->pgno, 0, &pagep)) != 0) {
+               (void)__db_pgerr(file_dbp, argp->pgno);
+               pagep = NULL;
+               goto out;
+       }
+       bk = GET_BKEYDATA(pagep, argp->indx);
+
+       modified = 0;
+       cmp_n = log_compare(lsnp, &LSN(pagep));
+       cmp_p = log_compare(&LSN(pagep), &argp->lsn);
+       if (cmp_p == 0 && redo) {
+               /*
+                * Need to redo update described.
+                *
+                * Re-build the replacement item.
+                */
+               memset(&dbt, 0, sizeof(dbt));
+               dbt.size = argp->prefix + argp->suffix + argp->repl.size;
+               if ((dbt.data = __db_malloc(dbt.size)) == NULL) {
+                       ret = ENOMEM;
+                       goto err;
+               }
+               p = dbt.data;
+               memcpy(p, bk->data, argp->prefix);
+               p += argp->prefix;
+               memcpy(p, argp->repl.data, argp->repl.size);
+               p += argp->repl.size;
+               memcpy(p, bk->data + (bk->len - argp->suffix), argp->suffix);
+
+               ret = __bam_ritem(file_dbp, pagep, argp->indx, &dbt);
+               __db_free(dbt.data);
+               if (ret != 0)
+                       goto err;
+
+               LSN(pagep) = *lsnp;
+               modified = 1;
+       } else if (cmp_n == 0 && !redo) {
+               /*
+                * Need to undo update described.
+                *
+                * Re-build the original item.
+                */
+               memset(&dbt, 0, sizeof(dbt));
+               dbt.size = argp->prefix + argp->suffix + argp->orig.size;
+               if ((dbt.data = __db_malloc(dbt.size)) == NULL) {
+                       ret = ENOMEM;
+                       goto err;
+               }
+               p = dbt.data;
+               memcpy(p, bk->data, argp->prefix);
+               p += argp->prefix;
+               memcpy(p, argp->orig.data, argp->orig.size);
+               p += argp->orig.size;
+               memcpy(p, bk->data + (bk->len - argp->suffix), argp->suffix);
+
+               ret = __bam_ritem(file_dbp, pagep, argp->indx, &dbt);
+               __db_free(dbt.data);
+               if (ret != 0)
+                       goto err;
+
+               /* Reset the deleted flag, if necessary. */
+               if (argp->isdeleted)
+                       B_DSET(GET_BKEYDATA(pagep, argp->indx)->type);
+
+               LSN(pagep) = argp->lsn;
+               modified = 1;
+       }
+       if ((ret = memp_fput(mpf, pagep, modified ? DB_MPOOL_DIRTY : 0)) == 0)
+               *lsnp = argp->prev_lsn;
+
+       if (0) {
+err:           (void)memp_fput(mpf, pagep, 0);
+       }
+out:   REC_CLOSE;
+}
index f7c5cff..5e1cbc4 100644 (file)
@@ -8,7 +8,7 @@
 #include "config.h"
 
 #ifndef lint
-static const char sccsid[] = "@(#)bt_recno.c   10.19 (Sleepycat) 9/20/97";
+static const char sccsid[] = "@(#)bt_recno.c   10.22 (Sleepycat) 10/25/97";
 #endif /* not lint */
 
 #ifndef NO_SYSTEM_INCLUDES
@@ -75,7 +75,7 @@ __ram_open(dbp, type, dbinfo)
        ret = 0;
 
        /* Allocate and initialize the private RECNO structure. */
-       if ((rp = (RECNO *)calloc(1, sizeof(*rp))) == NULL)
+       if ((rp = (RECNO *)__db_calloc(1, sizeof(*rp))) == NULL)
                return (ENOMEM);
 
        if (dbinfo != NULL) {
@@ -140,7 +140,7 @@ __ram_open(dbp, type, dbinfo)
 
 err:   /* If we mmap'd a source file, discard it. */
        if (rp->re_smap != NULL)
-               (void)__db_munmap(rp->re_smap, rp->re_msize);
+               (void)__db_unmap(rp->re_smap, rp->re_msize);
 
        /* If we opened a source file, discard it. */
        if (rp->re_fd != -1)
@@ -151,7 +151,7 @@ err:        /* If we mmap'd a source file, discard it. */
        /* If we allocated room for key/data return, discard it. */
        t = dbp->internal;
        if (t != NULL && t->bt_rkey.data != NULL)
-               free(t->bt_rkey.data);
+               __db_free(t->bt_rkey.data);
 
        FREE(rp, sizeof(*rp));
 
@@ -175,10 +175,10 @@ __ram_cursor(dbp, txn, dbcp)
 
        DEBUG_LWRITE(dbp, txn, "ram_cursor", NULL, NULL, 0);
 
-       if ((dbc = (DBC *)calloc(1, sizeof(DBC))) == NULL)
+       if ((dbc = (DBC *)__db_calloc(1, sizeof(DBC))) == NULL)
                return (ENOMEM);
-       if ((cp = (RCURSOR *)calloc(1, sizeof(RCURSOR))) == NULL) {
-               free(dbc);
+       if ((cp = (RCURSOR *)__db_calloc(1, sizeof(RCURSOR))) == NULL) {
+               __db_free(dbc);
                return (ENOMEM);
        }
 
@@ -359,7 +359,7 @@ __ram_close(argdbp)
 
        /* Close any underlying mmap region. */
        if (rp->re_smap != NULL)
-               (void)__db_munmap(rp->re_smap, rp->re_msize);
+               (void)__db_unmap(rp->re_smap, rp->re_msize);
 
        /* Close any backing source file descriptor. */
        if (rp->re_fd != -1)
@@ -814,8 +814,8 @@ __ram_update(dbp, recno, can_create)
        if (F_ISSET(dbp, DB_RE_FIXEDLEN)) {
                if (t->bt_rdata.ulen < rp->re_len) {
                        t->bt_rdata.data = t->bt_rdata.data == NULL ?
-                           (void *)malloc(rp->re_len) :
-                           (void *)realloc(t->bt_rdata.data, rp->re_len);
+                           (void *)__db_malloc(rp->re_len) :
+                           (void *)__db_realloc(t->bt_rdata.data, rp->re_len);
                        if (t->bt_rdata.data == NULL) {
                                t->bt_rdata.ulen = 0;
                                return (ENOMEM);
@@ -853,7 +853,7 @@ __ram_source(dbp, rp, fname)
 
        oflags = F_ISSET(dbp, DB_AM_RDONLY) ? DB_RDONLY : 0;
        if ((ret =
-           __db_fdopen(rp->re_source, oflags, oflags, 0, &rp->re_fd)) != 0) {
+           __db_open(rp->re_source, oflags, oflags, 0, &rp->re_fd)) != 0) {
                __db_err(dbp->dbenv, "%s: %s", rp->re_source, strerror(ret));
                goto err;
        }
@@ -866,15 +866,16 @@ __ram_source(dbp, rp, fname)
         * compiler will perpetrate, doing the comparison in a portable way is
         * flatly impossible.  Hope that mmap fails if the file is too large.
         */
-       if ((ret =
-           __db_stat(dbp->dbenv, rp->re_source, rp->re_fd, &size, NULL)) != 0)
+       if ((ret = __db_ioinfo(rp->re_source, rp->re_fd, &size, NULL)) != 0) {
+               __db_err(dbp->dbenv, "%s: %s", rp->re_source, strerror(ret));
                goto err;
+       }
        if (size == 0) {
                F_SET(rp, RECNO_EOF);
                return (0);
        }
 
-       if ((ret = __db_mmap(rp->re_fd, (size_t)size, 1, 1, &rp->re_smap)) != 0)
+       if ((ret = __db_map(rp->re_fd, (size_t)size, 1, 1, &rp->re_smap)) != 0)
                goto err;
        rp->re_cmap = rp->re_smap;
        rp->re_emap = (u_int8_t *)rp->re_smap + (rp->re_msize = size);
@@ -940,7 +941,7 @@ __ram_writeback(dbp)
         * open will fail.
         */
        if (rp->re_smap != NULL) {
-               (void)__db_munmap(rp->re_smap, rp->re_msize);
+               (void)__db_unmap(rp->re_smap, rp->re_msize);
                rp->re_smap = NULL;
        }
 
@@ -951,7 +952,7 @@ __ram_writeback(dbp)
        }
 
        /* Open the file, truncating it. */
-       if ((ret = __db_fdopen(rp->re_source,
+       if ((ret = __db_open(rp->re_source,
            DB_SEQUENTIAL | DB_TRUNCATE,
            DB_SEQUENTIAL | DB_TRUNCATE, 0, &fd)) != 0) {
                __db_err(dbp->dbenv, "%s: %s", rp->re_source, strerror(ret));
@@ -974,7 +975,7 @@ __ram_writeback(dbp)
         */
        delim = rp->re_delim;
        if (F_ISSET(dbp, DB_RE_FIXEDLEN)) {
-               if ((pad = malloc(rp->re_len)) == NULL) {
+               if ((pad = (u_int8_t *)__db_malloc(rp->re_len)) == NULL) {
                        ret = ENOMEM;
                        goto err;
                }
@@ -1051,8 +1052,8 @@ __ram_fmap(dbp, top)
        rp = t->bt_recno;
        if (t->bt_rdata.ulen < rp->re_len) {
                t->bt_rdata.data = t->bt_rdata.data == NULL ?
-                   (void *)malloc(rp->re_len) :
-                   (void *)realloc(t->bt_rdata.data, rp->re_len);
+                   (void *)__db_malloc(rp->re_len) :
+                   (void *)__db_realloc(t->bt_rdata.data, rp->re_len);
                if (t->bt_rdata.data == NULL) {
                        t->bt_rdata.ulen = 0;
                        return (ENOMEM);
index fa3e018..a21a820 100644 (file)
@@ -47,7 +47,7 @@
 #include "config.h"
 
 #ifndef lint
-static const char sccsid[] = "@(#)bt_search.c  10.7 (Sleepycat) 9/3/97";
+static const char sccsid[] = "@(#)bt_search.c  10.8 (Sleepycat) 10/25/97";
 #endif /* not lint */
 
 #ifndef NO_SYSTEM_INCLUDES
@@ -323,7 +323,7 @@ __bam_stkgrow(t)
 
        entries = t->bt_esp - t->bt_sp;
 
-       if ((p = (EPG *)calloc(entries * 2, sizeof(EPG))) == NULL)
+       if ((p = (EPG *)__db_calloc(entries * 2, sizeof(EPG))) == NULL)
                return (ENOMEM);
        memcpy(p, t->bt_sp, entries * sizeof(EPG));
        if (t->bt_sp != t->bt_stack)
index 25cfacc..bc09131 100644 (file)
@@ -44,7 +44,7 @@
 #include "config.h"
 
 #ifndef lint
-static const char sccsid[] = "@(#)bt_split.c   10.14 (Sleepycat) 9/3/97";
+static const char sccsid[] = "@(#)bt_split.c   10.17 (Sleepycat) 11/2/97";
 #endif /* not lint */
 
 #ifndef NO_SYSTEM_INCLUDES
@@ -255,7 +255,7 @@ __bam_page(dbp, pp, cp)
            cp->page->level, TYPE(cp->page));
 
        /* Create new left page for the split. */
-       if ((lp = (PAGE *)malloc(dbp->pgsize)) == NULL) {
+       if ((lp = (PAGE *)__db_malloc(dbp->pgsize)) == NULL) {
                ret = ENOMEM;
                goto err;
        }
@@ -389,6 +389,9 @@ __bam_broot(dbp, rootp, lp, rp)
        P_INIT(rootp, dbp->pgsize,
            PGNO_ROOT, PGNO_INVALID, PGNO_INVALID, lp->level + 1, P_IBTREE);
 
+       memset(&data, 0, sizeof(data));
+       memset(&hdr, 0, sizeof(hdr));
+
        /*
         * The btree comparison code guarantees that the left-most key on any
         * level of the tree is never used, so it doesn't need to be filled in.
@@ -399,15 +402,12 @@ __bam_broot(dbp, rootp, lp, rp)
        if (F_ISSET(dbp, DB_BT_RECNUM)) {
                bi.nrecs = __bam_total(lp);
                RE_NREC_SET(rootp, bi.nrecs);
-       }
-       memset(&hdr, 0, sizeof(hdr));
+       } else
+               bi.nrecs = 0;
        hdr.data = &bi;
        hdr.size = SSZA(BINTERNAL, data);
-       memset(&data, 0, sizeof(data));
-       data.data = (char *)"";
-       data.size = 0;
        if ((ret =
-           __db_pitem(dbp, rootp, 0, BINTERNAL_SIZE(0), &hdr, &data)) != 0)
+           __db_pitem(dbp, rootp, 0, BINTERNAL_SIZE(0), &hdr, NULL)) != 0)
                return (ret);
 
        switch (TYPE(rp)) {
@@ -431,9 +431,10 @@ __bam_broot(dbp, rootp, lp, rp)
                        return (ret);
 
                /* Increment the overflow ref count. */
-               if (B_TYPE(child_bi->type) == B_OVERFLOW && (ret =
-                   __db_ioff(dbp, ((BOVERFLOW *)(child_bi->data))->pgno)) != 0)
-                       return (ret);
+               if (B_TYPE(child_bi->type) == B_OVERFLOW)
+                       if ((ret = __db_ovref(dbp,
+                           ((BOVERFLOW *)(child_bi->data))->pgno, 1)) != 0)
+                               return (ret);
                break;
        case P_LBTREE:
                /* Copy the first key of the child page onto the root page. */
@@ -473,9 +474,10 @@ __bam_broot(dbp, rootp, lp, rp)
                                return (ret);
 
                        /* Increment the overflow ref count. */
-                       if (B_TYPE(child_bk->type) == B_OVERFLOW && (ret =
-                           __db_ioff(dbp, ((BOVERFLOW *)child_bk)->pgno)) != 0)
-                               return (ret);
+                       if (B_TYPE(child_bk->type) == B_OVERFLOW)
+                               if ((ret = __db_ovref(dbp,
+                                   ((BOVERFLOW *)child_bk)->pgno, 1)) != 0)
+                                       return (ret);
                        break;
                default:
                        return (__db_pgfmt(dbp, rp->pgno));
@@ -604,9 +606,10 @@ __bam_pinsert(dbp, parent, lchild, rchild)
                        return (ret);
 
                /* Increment the overflow ref count. */
-               if (B_TYPE(child_bi->type) == B_OVERFLOW && (ret =
-                   __db_ioff(dbp, ((BOVERFLOW *)(child_bi->data))->pgno)) != 0)
-                       return (ret);
+               if (B_TYPE(child_bi->type) == B_OVERFLOW)
+                       if ((ret = __db_ovref(dbp,
+                           ((BOVERFLOW *)(child_bi->data))->pgno, 1)) != 0)
+                               return (ret);
                break;
        case P_LBTREE:
                child_bk = GET_BKEYDATA(rchild, 0);
@@ -673,9 +676,10 @@ noprefix:                  nksize = child_bk->len;
                                return (ret);
 
                        /* Increment the overflow ref count. */
-                       if (B_TYPE(child_bk->type) == B_OVERFLOW && (ret =
-                           __db_ioff(dbp, ((BOVERFLOW *)child_bk)->pgno)) != 0)
-                               return (ret);
+                       if (B_TYPE(child_bk->type) == B_OVERFLOW)
+                               if ((ret = __db_ovref(dbp,
+                                   ((BOVERFLOW *)child_bk)->pgno, 1)) != 0)
+                                       return (ret);
                        break;
                default:
                        return (__db_pgfmt(dbp, rchild->pgno));
index ab3bc4c..e88b5da 100644 (file)
@@ -8,7 +8,7 @@
 #include "config.h"
 
 #ifndef lint
-static const char sccsid[] = "@(#)bt_stat.c    10.12 (Sleepycat) 9/3/97";
+static const char sccsid[] = "@(#)bt_stat.c    10.14 (Sleepycat) 10/25/97";
 #endif /* not lint */
 
 #ifndef NO_SYSTEM_INCLUDES
@@ -61,7 +61,7 @@ __bam_stat(argdbp, spp, db_malloc, flags)
 
        /* Allocate and clear the structure. */
        if ((sp = db_malloc == NULL ?
-           (DB_BTREE_STAT *)malloc(sizeof(*sp)) :
+           (DB_BTREE_STAT *)__db_malloc(sizeof(*sp)) :
            (DB_BTREE_STAT *)db_malloc(sizeof(*sp))) == NULL) {
                ret = ENOMEM;
                goto err;
@@ -100,14 +100,13 @@ __bam_stat(argdbp, spp, db_malloc, flags)
        if (F_ISSET(meta, BTM_RENUMBER))
                sp->bt_flags |= DB_RENUMBER;
 
-       /*
-        * Get the maxkey, minkey, re_len and re_pad fields from the
-        * metadata.
-        */
+       /* Get the remaining metadata fields. */
        sp->bt_minkey = meta->minkey;
        sp->bt_maxkey = meta->maxkey;
        sp->bt_re_len = meta->re_len;
        sp->bt_re_pad = meta->re_pad;
+       sp->bt_magic = meta->magic;
+       sp->bt_version = meta->version;
 
        /* Get the page size from the DB. */
        sp->bt_pagesize = dbp->pgsize;
index 7c8c4b1..6145696 100644 (file)
@@ -8,7 +8,7 @@
 #include "config.h"
 
 #ifndef lint
-static const char sccsid[] = "@(#)btree.src    10.4 (Sleepycat) 8/27/97";
+static const char sccsid[] = "@(#)btree.src    10.6 (Sleepycat) 11/2/97";
 #endif /* not lint */
 
 PREFIX bam
@@ -75,6 +75,7 @@ END
  *
  * pgno:       the page number of the page copied over the root.
  * pgdbt:      the page being copied on the root page.
+ * nrec:       the tree's record count.
  * rootent:    last entry on the root page.
  * rootlsn:    the root page's original lsn.
  */
@@ -82,6 +83,7 @@ BEGIN rsplit
 ARG    fileid          u_int32_t       lu
 ARG    pgno            db_pgno_t       lu
 DBT    pgdbt           DBT             s
+ARG    nrec            db_pgno_t       lu
 DBT    rootent         DBT             s
 POINTER rootlsn                DB_LSN *        lu
 END
@@ -135,3 +137,24 @@ ARG        pgno            db_pgno_t       lu
 POINTER        lsn             DB_LSN *        lu
 ARG    indx            u_int32_t       lu
 END
+
+/*
+ * BTREE-repl: used to log the replacement of an item.
+ *
+ * pgno:       the page modified.
+ * lsn:                the page's original lsn.
+ * orig:       the original data.
+ * new:                the replacement data.
+ * duplicate:  the prefix of the replacement that matches the original.
+ */
+BEGIN repl
+ARG    fileid          u_int32_t       lu
+ARG    pgno            db_pgno_t       lu
+POINTER        lsn             DB_LSN *        lu
+ARG    indx            u_int32_t       lu
+ARG    isdeleted       u_int32_t       lu
+DBT    orig            DBT             s
+DBT    repl            DBT             s
+ARG    prefix          u_int32_t       lu
+ARG    suffix          u_int32_t       lu
+END
index 353ee7b..45232bb 100644 (file)
@@ -57,7 +57,7 @@ int __bam_pg_alloc_log(logp, txnid, ret_lsnp, flags,
            + sizeof(pgno)
            + sizeof(ptype)
            + sizeof(next);
-       if ((logrec.data = (void *)malloc(logrec.size)) == NULL)
+       if ((logrec.data = (void *)__db_malloc(logrec.size)) == NULL)
                return (ENOMEM);
 
        bp = logrec.data;
@@ -92,7 +92,7 @@ int __bam_pg_alloc_log(logp, txnid, ret_lsnp, flags,
        ret = log_put(logp, ret_lsnp, (DBT *)&logrec, flags);
        if (txnid != NULL)
                txnid->last_lsn = *ret_lsnp;
-       free(logrec.data);
+       __db_free(logrec.data);
        return (ret);
 }
 
@@ -137,7 +137,7 @@ __bam_pg_alloc_print(notused1, dbtp, lsnp, notused3, notused4)
        printf("\tptype: %lu\n", (u_long)argp->ptype);
        printf("\tnext: %lu\n", (u_long)argp->next);
        printf("\n");
-       free(argp);
+       __db_free(argp);
        return (0);
 }
 
@@ -152,7 +152,7 @@ __bam_pg_alloc_read(recbuf, argpp)
        __bam_pg_alloc_args *argp;
        u_int8_t *bp;
 
-       argp = (__bam_pg_alloc_args *)malloc(sizeof(__bam_pg_alloc_args) +
+       argp = (__bam_pg_alloc_args *)__db_malloc(sizeof(__bam_pg_alloc_args) +
            sizeof(DB_TXN));
        if (argp == NULL)
                return (ENOMEM);
@@ -219,7 +219,7 @@ int __bam_pg_free_log(logp, txnid, ret_lsnp, flags,
            + sizeof(*meta_lsn)
            + sizeof(u_int32_t) + (header == NULL ? 0 : header->size)
            + sizeof(next);
-       if ((logrec.data = (void *)malloc(logrec.size)) == NULL)
+       if ((logrec.data = (void *)__db_malloc(logrec.size)) == NULL)
                return (ENOMEM);
 
        bp = logrec.data;
@@ -257,7 +257,7 @@ int __bam_pg_free_log(logp, txnid, ret_lsnp, flags,
        ret = log_put(logp, ret_lsnp, (DBT *)&logrec, flags);
        if (txnid != NULL)
                txnid->last_lsn = *ret_lsnp;
-       free(logrec.data);
+       __db_free(logrec.data);
        return (ret);
 }
 
@@ -308,7 +308,7 @@ __bam_pg_free_print(notused1, dbtp, lsnp, notused3, notused4)
        printf("\n");
        printf("\tnext: %lu\n", (u_long)argp->next);
        printf("\n");
-       free(argp);
+       __db_free(argp);
        return (0);
 }
 
@@ -323,7 +323,7 @@ __bam_pg_free_read(recbuf, argpp)
        __bam_pg_free_args *argp;
        u_int8_t *bp;
 
-       argp = (__bam_pg_free_args *)malloc(sizeof(__bam_pg_free_args) +
+       argp = (__bam_pg_free_args *)__db_malloc(sizeof(__bam_pg_free_args) +
            sizeof(DB_TXN));
        if (argp == NULL)
                return (ENOMEM);
@@ -400,7 +400,7 @@ int __bam_split_log(logp, txnid, ret_lsnp, flags,
            + sizeof(npgno)
            + sizeof(*nlsn)
            + sizeof(u_int32_t) + (pg == NULL ? 0 : pg->size);
-       if ((logrec.data = (void *)malloc(logrec.size)) == NULL)
+       if ((logrec.data = (void *)__db_malloc(logrec.size)) == NULL)
                return (ENOMEM);
 
        bp = logrec.data;
@@ -452,7 +452,7 @@ int __bam_split_log(logp, txnid, ret_lsnp, flags,
        ret = log_put(logp, ret_lsnp, (DBT *)&logrec, flags);
        if (txnid != NULL)
                txnid->last_lsn = *ret_lsnp;
-       free(logrec.data);
+       __db_free(logrec.data);
        return (ret);
 }
 
@@ -509,7 +509,7 @@ __bam_split_print(notused1, dbtp, lsnp, notused3, notused4)
        }
        printf("\n");
        printf("\n");
-       free(argp);
+       __db_free(argp);
        return (0);
 }
 
@@ -524,7 +524,7 @@ __bam_split_read(recbuf, argpp)
        __bam_split_args *argp;
        u_int8_t *bp;
 
-       argp = (__bam_split_args *)malloc(sizeof(__bam_split_args) +
+       argp = (__bam_split_args *)__db_malloc(sizeof(__bam_split_args) +
            sizeof(DB_TXN));
        if (argp == NULL)
                return (ENOMEM);
@@ -563,11 +563,11 @@ __bam_split_read(recbuf, argpp)
 /*
  * PUBLIC: int __bam_rsplit_log
  * PUBLIC:     __P((DB_LOG *, DB_TXN *, DB_LSN *, u_int32_t,
- * PUBLIC:     u_int32_t, db_pgno_t, DBT *, DBT *,
- * PUBLIC:     DB_LSN *));
+ * PUBLIC:     u_int32_t, db_pgno_t, DBT *, db_pgno_t,
+ * PUBLIC:     DBT *, DB_LSN *));
  */
 int __bam_rsplit_log(logp, txnid, ret_lsnp, flags,
-       fileid, pgno, pgdbt, rootent, rootlsn)
+       fileid, pgno, pgdbt, nrec, rootent, rootlsn)
        DB_LOG *logp;
        DB_TXN *txnid;
        DB_LSN *ret_lsnp;
@@ -575,6 +575,7 @@ int __bam_rsplit_log(logp, txnid, ret_lsnp, flags,
        u_int32_t fileid;
        db_pgno_t pgno;
        DBT *pgdbt;
+       db_pgno_t nrec;
        DBT *rootent;
        DB_LSN * rootlsn;
 {
@@ -597,9 +598,10 @@ int __bam_rsplit_log(logp, txnid, ret_lsnp, flags,
            + sizeof(fileid)
            + sizeof(pgno)
            + sizeof(u_int32_t) + (pgdbt == NULL ? 0 : pgdbt->size)
+           + sizeof(nrec)
            + sizeof(u_int32_t) + (rootent == NULL ? 0 : rootent->size)
            + sizeof(*rootlsn);
-       if ((logrec.data = (void *)malloc(logrec.size)) == NULL)
+       if ((logrec.data = (void *)__db_malloc(logrec.size)) == NULL)
                return (ENOMEM);
 
        bp = logrec.data;
@@ -623,6 +625,8 @@ int __bam_rsplit_log(logp, txnid, ret_lsnp, flags,
                memcpy(bp, pgdbt->data, pgdbt->size);
                bp += pgdbt->size;
        }
+       memcpy(bp, &nrec, sizeof(nrec));
+       bp += sizeof(nrec);
        if (rootent == NULL) {
                zero = 0;
                memcpy(bp, &zero, sizeof(u_int32_t));
@@ -645,7 +649,7 @@ int __bam_rsplit_log(logp, txnid, ret_lsnp, flags,
        ret = log_put(logp, ret_lsnp, (DBT *)&logrec, flags);
        if (txnid != NULL)
                txnid->last_lsn = *ret_lsnp;
-       free(logrec.data);
+       __db_free(logrec.data);
        return (ret);
 }
 
@@ -692,6 +696,7 @@ __bam_rsplit_print(notused1, dbtp, lsnp, notused3, notused4)
                        printf("%#x ", c);
        }
        printf("\n");
+       printf("\tnrec: %lu\n", (u_long)argp->nrec);
        printf("\trootent: ");
        for (i = 0; i < argp->rootent.size; i++) {
                c = ((char *)argp->rootent.data)[i];
@@ -704,7 +709,7 @@ __bam_rsplit_print(notused1, dbtp, lsnp, notused3, notused4)
        printf("\trootlsn: [%lu][%lu]\n",
            (u_long)argp->rootlsn.file, (u_long)argp->rootlsn.offset);
        printf("\n");
-       free(argp);
+       __db_free(argp);
        return (0);
 }
 
@@ -719,7 +724,7 @@ __bam_rsplit_read(recbuf, argpp)
        __bam_rsplit_args *argp;
        u_int8_t *bp;
 
-       argp = (__bam_rsplit_args *)malloc(sizeof(__bam_rsplit_args) +
+       argp = (__bam_rsplit_args *)__db_malloc(sizeof(__bam_rsplit_args) +
            sizeof(DB_TXN));
        if (argp == NULL)
                return (ENOMEM);
@@ -739,6 +744,8 @@ __bam_rsplit_read(recbuf, argpp)
        bp += sizeof(u_int32_t);
        argp->pgdbt.data = bp;
        bp += argp->pgdbt.size;
+       memcpy(&argp->nrec, bp, sizeof(argp->nrec));
+       bp += sizeof(argp->nrec);
        memcpy(&argp->rootent.size, bp, sizeof(u_int32_t));
        bp += sizeof(u_int32_t);
        argp->rootent.data = bp;
@@ -789,7 +796,7 @@ int __bam_adj_log(logp, txnid, ret_lsnp, flags,
            + sizeof(indx)
            + sizeof(indx_copy)
            + sizeof(is_insert);
-       if ((logrec.data = (void *)malloc(logrec.size)) == NULL)
+       if ((logrec.data = (void *)__db_malloc(logrec.size)) == NULL)
                return (ENOMEM);
 
        bp = logrec.data;
@@ -821,7 +828,7 @@ int __bam_adj_log(logp, txnid, ret_lsnp, flags,
        ret = log_put(logp, ret_lsnp, (DBT *)&logrec, flags);
        if (txnid != NULL)
                txnid->last_lsn = *ret_lsnp;
-       free(logrec.data);
+       __db_free(logrec.data);
        return (ret);
 }
 
@@ -865,7 +872,7 @@ __bam_adj_print(notused1, dbtp, lsnp, notused3, notused4)
        printf("\tindx_copy: %lu\n", (u_long)argp->indx_copy);
        printf("\tis_insert: %lu\n", (u_long)argp->is_insert);
        printf("\n");
-       free(argp);
+       __db_free(argp);
        return (0);
 }
 
@@ -880,7 +887,7 @@ __bam_adj_read(recbuf, argpp)
        __bam_adj_args *argp;
        u_int8_t *bp;
 
-       argp = (__bam_adj_args *)malloc(sizeof(__bam_adj_args) +
+       argp = (__bam_adj_args *)__db_malloc(sizeof(__bam_adj_args) +
            sizeof(DB_TXN));
        if (argp == NULL)
                return (ENOMEM);
@@ -948,7 +955,7 @@ int __bam_cadjust_log(logp, txnid, ret_lsnp, flags,
            + sizeof(indx)
            + sizeof(adjust)
            + sizeof(total);
-       if ((logrec.data = (void *)malloc(logrec.size)) == NULL)
+       if ((logrec.data = (void *)__db_malloc(logrec.size)) == NULL)
                return (ENOMEM);
 
        bp = logrec.data;
@@ -980,7 +987,7 @@ int __bam_cadjust_log(logp, txnid, ret_lsnp, flags,
        ret = log_put(logp, ret_lsnp, (DBT *)&logrec, flags);
        if (txnid != NULL)
                txnid->last_lsn = *ret_lsnp;
-       free(logrec.data);
+       __db_free(logrec.data);
        return (ret);
 }
 
@@ -1024,7 +1031,7 @@ __bam_cadjust_print(notused1, dbtp, lsnp, notused3, notused4)
        printf("\tadjust: %ld\n", (long)argp->adjust);
        printf("\ttotal: %ld\n", (long)argp->total);
        printf("\n");
-       free(argp);
+       __db_free(argp);
        return (0);
 }
 
@@ -1039,7 +1046,7 @@ __bam_cadjust_read(recbuf, argpp)
        __bam_cadjust_args *argp;
        u_int8_t *bp;
 
-       argp = (__bam_cadjust_args *)malloc(sizeof(__bam_cadjust_args) +
+       argp = (__bam_cadjust_args *)__db_malloc(sizeof(__bam_cadjust_args) +
            sizeof(DB_TXN));
        if (argp == NULL)
                return (ENOMEM);
@@ -1102,7 +1109,7 @@ int __bam_cdel_log(logp, txnid, ret_lsnp, flags,
            + sizeof(pgno)
            + sizeof(*lsn)
            + sizeof(indx);
-       if ((logrec.data = (void *)malloc(logrec.size)) == NULL)
+       if ((logrec.data = (void *)__db_malloc(logrec.size)) == NULL)
                return (ENOMEM);
 
        bp = logrec.data;
@@ -1130,7 +1137,7 @@ int __bam_cdel_log(logp, txnid, ret_lsnp, flags,
        ret = log_put(logp, ret_lsnp, (DBT *)&logrec, flags);
        if (txnid != NULL)
                txnid->last_lsn = *ret_lsnp;
-       free(logrec.data);
+       __db_free(logrec.data);
        return (ret);
 }
 
@@ -1172,7 +1179,7 @@ __bam_cdel_print(notused1, dbtp, lsnp, notused3, notused4)
            (u_long)argp->lsn.file, (u_long)argp->lsn.offset);
        printf("\tindx: %lu\n", (u_long)argp->indx);
        printf("\n");
-       free(argp);
+       __db_free(argp);
        return (0);
 }
 
@@ -1187,7 +1194,7 @@ __bam_cdel_read(recbuf, argpp)
        __bam_cdel_args *argp;
        u_int8_t *bp;
 
-       argp = (__bam_cdel_args *)malloc(sizeof(__bam_cdel_args) +
+       argp = (__bam_cdel_args *)__db_malloc(sizeof(__bam_cdel_args) +
            sizeof(DB_TXN));
        if (argp == NULL)
                return (ENOMEM);
@@ -1212,6 +1219,225 @@ __bam_cdel_read(recbuf, argpp)
 }
 
 /*
+ * PUBLIC: int __bam_repl_log
+ * PUBLIC:     __P((DB_LOG *, DB_TXN *, DB_LSN *, u_int32_t,
+ * PUBLIC:     u_int32_t, db_pgno_t, DB_LSN *, u_int32_t,
+ * PUBLIC:     u_int32_t, DBT *, DBT *, u_int32_t,
+ * PUBLIC:     u_int32_t));
+ */
+int __bam_repl_log(logp, txnid, ret_lsnp, flags,
+       fileid, pgno, lsn, indx, isdeleted, orig,
+       repl, prefix, suffix)
+       DB_LOG *logp;
+       DB_TXN *txnid;
+       DB_LSN *ret_lsnp;
+       u_int32_t flags;
+       u_int32_t fileid;
+       db_pgno_t pgno;
+       DB_LSN * lsn;
+       u_int32_t indx;
+       u_int32_t isdeleted;
+       DBT *orig;
+       DBT *repl;
+       u_int32_t prefix;
+       u_int32_t suffix;
+{
+       DBT logrec;
+       DB_LSN *lsnp, null_lsn;
+       u_int32_t zero;
+       u_int32_t rectype, txn_num;
+       int ret;
+       u_int8_t *bp;
+
+       rectype = DB_bam_repl;
+       txn_num = txnid == NULL ? 0 : txnid->txnid;
+       if (txnid == NULL) {
+               null_lsn.file = 0;
+               null_lsn.offset = 0;
+               lsnp = &null_lsn;
+       } else
+               lsnp = &txnid->last_lsn;
+       logrec.size = sizeof(rectype) + sizeof(txn_num) + sizeof(DB_LSN)
+           + sizeof(fileid)
+           + sizeof(pgno)
+           + sizeof(*lsn)
+           + sizeof(indx)
+           + sizeof(isdeleted)
+           + sizeof(u_int32_t) + (orig == NULL ? 0 : orig->size)
+           + sizeof(u_int32_t) + (repl == NULL ? 0 : repl->size)
+           + sizeof(prefix)
+           + sizeof(suffix);
+       if ((logrec.data = (void *)__db_malloc(logrec.size)) == NULL)
+               return (ENOMEM);
+
+       bp = logrec.data;
+       memcpy(bp, &rectype, sizeof(rectype));
+       bp += sizeof(rectype);
+       memcpy(bp, &txn_num, sizeof(txn_num));
+       bp += sizeof(txn_num);
+       memcpy(bp, lsnp, sizeof(DB_LSN));
+       bp += sizeof(DB_LSN);
+       memcpy(bp, &fileid, sizeof(fileid));
+       bp += sizeof(fileid);
+       memcpy(bp, &pgno, sizeof(pgno));
+       bp += sizeof(pgno);
+       if (lsn != NULL)
+               memcpy(bp, lsn, sizeof(*lsn));
+       else
+               memset(bp, 0, sizeof(*lsn));
+       bp += sizeof(*lsn);
+       memcpy(bp, &indx, sizeof(indx));
+       bp += sizeof(indx);
+       memcpy(bp, &isdeleted, sizeof(isdeleted));
+       bp += sizeof(isdeleted);
+       if (orig == NULL) {
+               zero = 0;
+               memcpy(bp, &zero, sizeof(u_int32_t));
+               bp += sizeof(u_int32_t);
+       } else {
+               memcpy(bp, &orig->size, sizeof(orig->size));
+               bp += sizeof(orig->size);
+               memcpy(bp, orig->data, orig->size);
+               bp += orig->size;
+       }
+       if (repl == NULL) {
+               zero = 0;
+               memcpy(bp, &zero, sizeof(u_int32_t));
+               bp += sizeof(u_int32_t);
+       } else {
+               memcpy(bp, &repl->size, sizeof(repl->size));
+               bp += sizeof(repl->size);
+               memcpy(bp, repl->data, repl->size);
+               bp += repl->size;
+       }
+       memcpy(bp, &prefix, sizeof(prefix));
+       bp += sizeof(prefix);
+       memcpy(bp, &suffix, sizeof(suffix));
+       bp += sizeof(suffix);
+#ifdef DEBUG
+       if ((u_int32_t)(bp - (u_int8_t *)logrec.data) != logrec.size)
+               fprintf(stderr, "Error in log record length");
+#endif
+       ret = log_put(logp, ret_lsnp, (DBT *)&logrec, flags);
+       if (txnid != NULL)
+               txnid->last_lsn = *ret_lsnp;
+       __db_free(logrec.data);
+       return (ret);
+}
+
+/*
+ * PUBLIC: int __bam_repl_print
+ * PUBLIC:    __P((DB_LOG *, DBT *, DB_LSN *, int, void *));
+ */
+
+int
+__bam_repl_print(notused1, dbtp, lsnp, notused3, notused4)
+       DB_LOG *notused1;
+       DBT *dbtp;
+       DB_LSN *lsnp;
+       int notused3;
+       void *notused4;
+{
+       __bam_repl_args *argp;
+       u_int32_t i;
+       int c, ret;
+
+       i = 0;
+       c = 0;
+       notused1 = NULL;
+       notused3 = 0;
+       notused4 = NULL;
+
+       if ((ret = __bam_repl_read(dbtp->data, &argp)) != 0)
+               return (ret);
+       printf("[%lu][%lu]bam_repl: rec: %lu txnid %lx prevlsn [%lu][%lu]\n",
+           (u_long)lsnp->file,
+           (u_long)lsnp->offset,
+           (u_long)argp->type,
+           (u_long)argp->txnid->txnid,
+           (u_long)argp->prev_lsn.file,
+           (u_long)argp->prev_lsn.offset);
+       printf("\tfileid: %lu\n", (u_long)argp->fileid);
+       printf("\tpgno: %lu\n", (u_long)argp->pgno);
+       printf("\tlsn: [%lu][%lu]\n",
+           (u_long)argp->lsn.file, (u_long)argp->lsn.offset);
+       printf("\tindx: %lu\n", (u_long)argp->indx);
+       printf("\tisdeleted: %lu\n", (u_long)argp->isdeleted);
+       printf("\torig: ");
+       for (i = 0; i < argp->orig.size; i++) {
+               c = ((char *)argp->orig.data)[i];
+               if (isprint(c) || c == 0xa)
+                       putchar(c);
+               else
+                       printf("%#x ", c);
+       }
+       printf("\n");
+       printf("\trepl: ");
+       for (i = 0; i < argp->repl.size; i++) {
+               c = ((char *)argp->repl.data)[i];
+               if (isprint(c) || c == 0xa)
+                       putchar(c);
+               else
+                       printf("%#x ", c);
+       }
+       printf("\n");
+       printf("\tprefix: %lu\n", (u_long)argp->prefix);
+       printf("\tsuffix: %lu\n", (u_long)argp->suffix);
+       printf("\n");
+       __db_free(argp);
+       return (0);
+}
+
+/*
+ * PUBLIC: int __bam_repl_read __P((void *, __bam_repl_args **));
+ */
+int
+__bam_repl_read(recbuf, argpp)
+       void *recbuf;
+       __bam_repl_args **argpp;
+{
+       __bam_repl_args *argp;
+       u_int8_t *bp;
+
+       argp = (__bam_repl_args *)__db_malloc(sizeof(__bam_repl_args) +
+           sizeof(DB_TXN));
+       if (argp == NULL)
+               return (ENOMEM);
+       argp->txnid = (DB_TXN *)&argp[1];
+       bp = recbuf;
+       memcpy(&argp->type, bp, sizeof(argp->type));
+       bp += sizeof(argp->type);
+       memcpy(&argp->txnid->txnid,  bp, sizeof(argp->txnid->txnid));
+       bp += sizeof(argp->txnid->txnid);
+       memcpy(&argp->prev_lsn, bp, sizeof(DB_LSN));
+       bp += sizeof(DB_LSN);
+       memcpy(&argp->fileid, bp, sizeof(argp->fileid));
+       bp += sizeof(argp->fileid);
+       memcpy(&argp->pgno, bp, sizeof(argp->pgno));
+       bp += sizeof(argp->pgno);
+       memcpy(&argp->lsn, bp,  sizeof(argp->lsn));
+       bp += sizeof(argp->lsn);
+       memcpy(&argp->indx, bp, sizeof(argp->indx));
+       bp += sizeof(argp->indx);
+       memcpy(&argp->isdeleted, bp, sizeof(argp->isdeleted));
+       bp += sizeof(argp->isdeleted);
+       memcpy(&argp->orig.size, bp, sizeof(u_int32_t));
+       bp += sizeof(u_int32_t);
+       argp->orig.data = bp;
+       bp += argp->orig.size;
+       memcpy(&argp->repl.size, bp, sizeof(u_int32_t));
+       bp += sizeof(u_int32_t);
+       argp->repl.data = bp;
+       bp += argp->repl.size;
+       memcpy(&argp->prefix, bp, sizeof(argp->prefix));
+       bp += sizeof(argp->prefix);
+       memcpy(&argp->suffix, bp, sizeof(argp->suffix));
+       bp += sizeof(argp->suffix);
+       *argpp = argp;
+       return (0);
+}
+
+/*
  * PUBLIC: int __bam_init_print __P((DB_ENV *));
  */
 int
@@ -1241,6 +1467,9 @@ __bam_init_print(dbenv)
        if ((ret = __db_add_recovery(dbenv,
            __bam_cdel_print, DB_bam_cdel)) != 0)
                return (ret);
+       if ((ret = __db_add_recovery(dbenv,
+           __bam_repl_print, DB_bam_repl)) != 0)
+               return (ret);
        return (0);
 }
 
@@ -1274,6 +1503,9 @@ __bam_init_recover(dbenv)
        if ((ret = __db_add_recovery(dbenv,
            __bam_cdel_recover, DB_bam_cdel)) != 0)
                return (ret);
+       if ((ret = __db_add_recovery(dbenv,
+           __bam_repl_recover, DB_bam_repl)) != 0)
+               return (ret);
        return (0);
 }
 
index 51d9262..74ba9ff 100644 (file)
@@ -8,7 +8,7 @@
 #include "config.h"
 
 #ifndef lint
-static const char sccsid[] = "@(#)db_appinit.c 10.33 (Sleepycat) 8/28/97";
+static const char sccsid[] = "@(#)db_appinit.c 10.36 (Sleepycat) 10/28/97";
 #endif /* not lint */
 
 #ifndef NO_SYSTEM_INCLUDES
@@ -93,6 +93,10 @@ db_appinit(db_home, db_config, dbenv, flags)
            LF_ISSET(RECOVERY_FLAGS) != RECOVERY_FLAGS)
                return (__db_ferr(dbenv, "db_appinit", 1));
 
+       /* Convert the db_appinit(3) flags. */
+       if (LF_ISSET(DB_THREAD))
+               F_SET(dbenv, DB_ENV_THREAD);
+
        fp = NULL;
 
        /* Set the database home. */
@@ -126,7 +130,7 @@ db_appinit(db_home, db_config, dbenv, flags)
                goto err;
 
        /* Indicate that the path names have been set. */
-       F_SET(dbenv, DB_APP_INIT);
+       F_SET(dbenv, DB_ENV_APPINIT);
 
        /*
         * If we are doing recovery, remove all the regions.
@@ -300,7 +304,8 @@ __db_appname(dbenv, appname, dir, file, fdp, namep)
         * return.
         */
        if (file != NULL && __db_abspath(file))
-               return ((*namep = (char *)strdup(file)) == NULL ? ENOMEM : 0);
+               return ((*namep =
+                   (char *)__db_strdup(file)) == NULL ? ENOMEM : 0);
        if (dir != NULL && __db_abspath(dir)) {
                a = dir;
                goto done;
@@ -335,7 +340,7 @@ __db_appname(dbenv, appname, dir, file, fdp, namep)
         */
 retry: switch (appname) {
        case DB_APP_NONE:
-               if (dbenv == NULL || !F_ISSET(dbenv, DB_APP_INIT)) {
+               if (dbenv == NULL || !F_ISSET(dbenv, DB_ENV_APPINIT)) {
                        if (dir == NULL)
                                goto tmp;
                        a = dir;
@@ -355,7 +360,7 @@ retry:      switch (appname) {
                        tmp_create = 1;
                        goto tmp;
                }
-               if (dbenv == NULL || !F_ISSET(dbenv, DB_APP_INIT))
+               if (dbenv == NULL || !F_ISSET(dbenv, DB_ENV_APPINIT))
                        a = PATH_DOT;
                else {
                        a = dbenv->db_home;
@@ -367,7 +372,7 @@ retry:      switch (appname) {
                }
                break;
        case DB_APP_LOG:
-               if (dbenv == NULL || !F_ISSET(dbenv, DB_APP_INIT)) {
+               if (dbenv == NULL || !F_ISSET(dbenv, DB_ENV_APPINIT)) {
                        if (dir == NULL)
                                goto tmp;
                        a = dir;
@@ -385,7 +390,7 @@ retry:      switch (appname) {
                }
 
                tmp_create = 1;
-               if (dbenv == NULL || !F_ISSET(dbenv, DB_APP_INIT))
+               if (dbenv == NULL || !F_ISSET(dbenv, DB_ENV_APPINIT))
                        goto tmp;
                else {
                        a = dbenv->db_home;
@@ -396,7 +401,7 @@ retry:      switch (appname) {
 
        /* Reference a file from the appropriate temporary directory. */
        if (0) {
-tmp:           if (dbenv == NULL || !F_ISSET(dbenv, DB_APP_INIT)) {
+tmp:           if (dbenv == NULL || !F_ISSET(dbenv, DB_ENV_APPINIT)) {
                        memset(&etmp, 0, sizeof(etmp));
                        if ((ret = __db_tmp_dir(&etmp, DB_USE_ENVIRON)) != 0)
                                return (ret);
@@ -412,7 +417,7 @@ done:       len =
            (c == NULL ? 0 : strlen(c) + 1) +
            (file == NULL ? 0 : strlen(file) + 1);
 
-       if ((start = (char *)malloc(len)) == NULL) {
+       if ((start = (char *)__db_malloc(len)) == NULL) {
                __db_err(dbenv, "%s", strerror(ENOMEM));
                if (tmp_free)
                        FREES(etmp.db_tmp_dir);
@@ -484,7 +489,7 @@ __db_home(dbenv, db_home, flags)
        if (p == NULL)
                return (0);
 
-       if ((dbenv->db_home = (char *)strdup(p)) == NULL) {
+       if ((dbenv->db_home = (char *)__db_strdup(p)) == NULL) {
                __db_err(dbenv, "%s", strerror(ENOMEM));
                return (ENOMEM);
        }
@@ -509,7 +514,7 @@ __db_parse(dbenv, s)
         * We need to strdup the argument in case the caller passed us
         * static data.
         */
-       if ((local_s = (char *)strdup(s)) == NULL)
+       if ((local_s = (char *)__db_strdup(s)) == NULL)
                return (ENOMEM);
 
        tp = local_s;
@@ -526,14 +531,15 @@ illegal:  ret = EINVAL;
 #define        DATA_INIT_CNT   20                      /* Start with 20 data slots. */
        if (!strcmp(name, "DB_DATA_DIR")) {
                if (dbenv->db_data_dir == NULL) {
-                       if ((dbenv->db_data_dir = (char **)calloc(DATA_INIT_CNT,
+                       if ((dbenv->db_data_dir =
+                           (char **)__db_calloc(DATA_INIT_CNT,
                            sizeof(char **))) == NULL)
                                goto nomem;
                        dbenv->data_cnt = DATA_INIT_CNT;
                } else if (dbenv->data_next == dbenv->data_cnt - 1) {
                        dbenv->data_cnt *= 2;
                        if ((dbenv->db_data_dir =
-                           (char **)realloc(dbenv->db_data_dir,
+                           (char **)__db_realloc(dbenv->db_data_dir,
                            dbenv->data_cnt * sizeof(char **))) == NULL)
                                goto nomem;
                }
@@ -549,7 +555,7 @@ illegal:    ret = EINVAL;
        } else
                goto err;
 
-       if ((*p = (char *)strdup(value)) == NULL) {
+       if ((*p = (char *)__db_strdup(value)) == NULL) {
 nomem:         ret = ENOMEM;
                __db_err(dbenv, "%s", strerror(ENOMEM));
        }
@@ -623,7 +629,7 @@ __db_tmp_dir(dbenv, flags)
                if (!Special2FSSpec(kTemporaryFolderType,
                    kOnSystemDisk, 0, &spec)) {
                        p = FSp2FullPath(&spec);
-                       sTempFolder = malloc(strlen(p) + 1);
+                       sTempFolder = __db_malloc(strlen(p) + 1);
                        strcpy(sTempFolder, p);
                        p = sTempFolder;
                }
@@ -639,7 +645,7 @@ __db_tmp_dir(dbenv, flags)
        if (p == NULL)
                return (0);
 
-       if ((dbenv->db_tmp_dir = (char *)strdup(p)) == NULL) {
+       if ((dbenv->db_tmp_dir = (char *)__db_strdup(p)) == NULL) {
                __db_err(dbenv, "%s", strerror(ENOMEM));
                return (ENOMEM);
        }
@@ -722,7 +728,7 @@ __db_tmp_open(dbenv, dir, fdp)
                (void)sigprocmask(SIG_BLOCK, &set, &oset);
 #endif
 #define        DB_TEMPOPEN     DB_CREATE | DB_EXCL | DB_TEMPORARY
-               if ((ret = __db_fdopen(buf,
+               if ((ret = __db_open(buf,
                    DB_TEMPOPEN, DB_TEMPOPEN, S_IRUSR | S_IWUSR, fdp)) == 0) {
 #ifdef HAVE_SIGFILLSET
                        (void)sigprocmask(SIG_SETMASK, &oset, NULL);
index 2e94673..ac0176d 100644 (file)
@@ -11,7 +11,7 @@
 static const char copyright[] =
 "@(#) Copyright (c) 1997\n\
        Sleepycat Software Inc.  All rights reserved.\n";
-static const char sccsid[] = "@(#)db_apprec.c  10.16 (Sleepycat) 8/27/97";
+static const char sccsid[] = "@(#)db_apprec.c  10.18 (Sleepycat) 9/30/97";
 #endif
 
 #ifndef NO_SYSTEM_INCLUDES
@@ -31,12 +31,6 @@ static const char sccsid[] = "@(#)db_apprec.c        10.16 (Sleepycat) 8/27/97";
 #include "txn.h"
 #include "common_ext.h"
 
-#define        FREE_DBT(L, D) {                                                \
-       if (F_ISSET((L), DB_AM_THREAD) && (D).data != NULL)             \
-               free((D).data);                                         \
-               (D).data = NULL;                                        \
-       }                                                               \
-
 /*
  * __db_apprec --
  *     Perform recovery.
@@ -52,34 +46,41 @@ __db_apprec(dbenv, flags)
        DB_LOG *lp;
        DB_LSN ckp_lsn, first_lsn, lsn, tmp_lsn;
        time_t now;
-       int first_flag, ret;
+       int first_flag, is_thread, ret;
        void *txninfo;
 
+       lp = dbenv->lg_info;
+
        /* Initialize the transaction list. */
        if ((ret = __db_txnlist_init(&txninfo)) != 0)
                return (ret);
 
        /*
+        * Save the state of the thread flag -- we don't need it on at the
+        * moment because we're single-threaded until recovery is complete.
+        */
+       is_thread = F_ISSET(lp, DB_AM_THREAD);
+       F_CLR(lp, DB_AM_THREAD);
+
+       /*
         * Read forward through the log, opening the appropriate files so that
         * we can call recovery routines.  In general, we start at the last
         * checkpoint prior to the last checkpointed LSN.  For catastrophic
         * recovery, we begin at the first LSN that appears in any log file
         * (log_get figures this out for us when we pass it the DB_FIRST flag).
         */
-       lp = dbenv->lg_info;
        if (LF_ISSET(DB_RECOVER_FATAL))
                first_flag = DB_FIRST;
        else {
-               if ((ret = __log_findckp(lp, &lsn)) == DB_NOTFOUND)
+               if ((ret = __log_findckp(lp, &lsn)) == DB_NOTFOUND) {
+                       F_SET(lp, is_thread);
                        return (0);
+               }
                first_flag = DB_SET;
        }
 
        /* If we're a threaded application, we have to allocate space. */
        memset(&data, 0, sizeof(data));
-       if (F_ISSET(lp, DB_AM_THREAD))
-               F_SET(&data, DB_DBT_MALLOC);
-
        if ((ret = log_get(lp, &lsn, &data, first_flag)) != 0) {
                __db_err(dbenv, "Failure: unable to get log record");
                if (first_flag == DB_SET)
@@ -93,7 +94,6 @@ __db_apprec(dbenv, flags)
        first_lsn = lsn;
        for (;;) {
                ret = __db_dispatch(lp, &data, &lsn, TXN_OPENFILES, txninfo);
-               FREE_DBT(lp, data);
                if (ret != 0 && ret != DB_TXN_CKP)
                        goto msgerr;
                if ((ret =
@@ -103,7 +103,6 @@ __db_apprec(dbenv, flags)
                        break;
                }
        }
-       FREE_DBT(lp, data);
 
        /*
         * Initialize the ckp_lsn to 0,0.  If we never find a valid
@@ -116,7 +115,6 @@ __db_apprec(dbenv, flags)
                tmp_lsn = lsn;
                ret = __db_dispatch(lp,
                    &data, &lsn, TXN_BACKWARD_ROLL, txninfo);
-               FREE_DBT(lp, data);
                if (ret == DB_TXN_CKP) {
                        if (IS_ZERO_LSN(ckp_lsn))
                                ckp_lsn = tmp_lsn;
@@ -124,20 +122,17 @@ __db_apprec(dbenv, flags)
                } else if (ret != 0)
                        goto msgerr;
        }
-       FREE_DBT(lp, data);
        if (ret != 0 && ret != DB_NOTFOUND)
                goto err;
 
        for (ret = log_get(lp, &lsn, &data, DB_NEXT);
            ret == 0; ret = log_get(lp, &lsn, &data, DB_NEXT)) {
                ret = __db_dispatch(lp, &data, &lsn, TXN_FORWARD_ROLL, txninfo);
-               FREE_DBT(lp, data);
                if (ret == DB_TXN_CKP)
                        ret = 0;
                else if (ret != 0)
                        goto msgerr;
        }
-       FREE_DBT(lp, data);
        if (ret != DB_NOTFOUND)
                goto err;
 
@@ -165,11 +160,12 @@ __db_apprec(dbenv, flags)
                    (u_long)dbenv->tx_info->region->last_ckp.offset);
        }
 
+       F_SET(lp, is_thread);
        return (0);
 
 msgerr:        __db_err(dbenv, "Recovery function for LSN %lu %lu failed",
            (u_long)lsn.file, (u_long)lsn.offset);
 
-err:   FREE_DBT(lp, data);
+err:   F_SET(lp, is_thread);
        return (ret);
 }
index a8d7715..e486132 100644 (file)
@@ -8,20 +8,20 @@
 #include "config.h"
 
 #ifndef lint
-static const char sccsid[] = "@(#)db_byteorder.c       10.3 (Sleepycat) 6/21/97";
+static const char sccsid[] = "@(#)db_byteorder.c       10.4 (Sleepycat) 9/4/97";
 #endif /* not lint */
 
 #ifndef NO_SYSTEM_INCLUDES
 #include <sys/types.h>
 
-#include <errno.h>
+#ifdef HAVE_ENDIAN_H
+#include <endian.h>
+#if BYTE_ORDER == BIG_ENDIAN
+#define        WORDS_BIGENDIAN 1
+#endif
 #endif
 
-#ifdef HAVE_ENDIAN_H
-# include <endian.h>
-# if BYTE_ORDER == BIG_ENDIAN
-#  define WORDS_BIGENDIAN 1
-# endif
+#include <errno.h>
 #endif
 
 #include "db_int.h"
index 86d79a8..3e8cd2d 100644 (file)
@@ -43,7 +43,7 @@
 #include "config.h"
 
 #ifndef lint
-static const char sccsid[] = "@(#)db_region.c  10.13 (Sleepycat) 8/27/97";
+static const char sccsid[] = "@(#)db_region.c  10.15 (Sleepycat) 10/25/97";
 #endif /* not lint */
 
 #ifndef NO_SYSTEM_INCLUDES
@@ -114,7 +114,7 @@ __db_rcreate(dbenv, appname, path, file, mode, size, fdp, retp)
         * attempts to create the region will return failure in one of the
         * attempts.
         */
-       if (fd == -1 && (ret = __db_fdopen(name,
+       if (fd == -1 && (ret = __db_open(name,
            DB_CREATE | DB_EXCL, DB_CREATE | DB_EXCL, mode, &fd)) != 0) {
                if (ret != EEXIST)
                        __db_err(dbenv,
@@ -131,6 +131,42 @@ __db_rcreate(dbenv, appname, path, file, mode, size, fdp, retp)
        if ((ret = __db_rmap(dbenv, fd, size, &rp)) != 0)
                goto err;
 
+       /* Initialize the region. */
+       if ((ret = __db_rinit(dbenv, rp, fd, size, 1)) != 0)
+               goto err;
+
+       if (name != NULL)
+               FREES(name);
+
+       *(void **)retp = rp;
+       return (0);
+
+err:   if (fd != -1) {
+               if (rp != NULL)
+                       (void)__db_unmap(rp, rp->size);
+               (void)__db_unlink(name);
+               (void)__db_close(fd);
+       }
+       if (name != NULL)
+               FREES(name);
+       return (ret);
+}
+
+/*
+ * __db_rinit --
+ *     Initialize the region.
+ *
+ * PUBLIC: int __db_rinit __P((DB_ENV *, RLAYOUT *, int, size_t, int));
+ */
+int
+__db_rinit(dbenv, rp, fd, size, lock_region)
+       DB_ENV *dbenv;
+       RLAYOUT *rp;
+       size_t size;
+       int fd, lock_region;
+{
+       int ret;
+
        /*
         * Initialize the common information.
         *
@@ -141,9 +177,12 @@ __db_rcreate(dbenv, appname, path, file, mode, size, fdp, retp)
         * file permissions games, but we can't because WNT filesystems won't
         * open a file mode 0.
         *
-        * So, the process that's creating the region always acquires the lock
-        * before the setting the version number.  Any process joining always
-        * checks the version number before attempting to acquire the lock.
+        * If the lock_region flag is set, the process creating the region
+        * acquires the lock before the setting the version number.  Any
+        * process joining the region checks the version number before
+        * attempting to acquire the lock.  (The lock_region flag may not be
+        * set -- the mpool code sometimes malloc's private regions but still
+        * needs to initialize them, specifically, the mutex for threads.)
         *
         * We have to check the version number first, because if the version
         * number has not been written, it's possible that the mutex has not
@@ -151,30 +190,16 @@ __db_rcreate(dbenv, appname, path, file, mode, size, fdp, retp)
         * random behavior.  If the version number isn't there (the file size
         * is too small) or it's 0, we know that the region is being created.
         */
-       (void)__db_mutex_init(&rp->lock, MUTEX_LOCK_OFFSET(rp, &rp->lock));
-       (void)__db_mutex_lock(&rp->lock,
-           fd, dbenv == NULL ? NULL : dbenv->db_yield);
+       __db_mutex_init(&rp->lock, MUTEX_LOCK_OFFSET(rp, &rp->lock));
+       if (lock_region && (ret = __db_mutex_lock(&rp->lock, fd)) != 0)
+               return (ret);
 
        rp->refcnt = 1;
        rp->size = size;
        rp->flags = 0;
        db_version(&rp->majver, &rp->minver, &rp->patch);
 
-       if (name != NULL)
-               FREES(name);
-
-       *(void **)retp = rp;
        return (0);
-
-err:   if (fd != -1) {
-               if (rp != NULL)
-                       (void)__db_munmap(rp, rp->size);
-               (void)__db_unlink(name);
-               (void)__db_close(fd);
-       }
-       if (name != NULL)
-               FREES(name);
-       return (ret);
 }
 
 /*
@@ -205,7 +230,7 @@ __db_ropen(dbenv, appname, path, file, flags, fdp, retp)
                return (ret);
 
        /* Open the file. */
-       if ((ret = __db_fdopen(name, flags, DB_MUTEXDEBUG, 0, &fd)) != 0) {
+       if ((ret = __db_open(name, flags, DB_MUTEXDEBUG, 0, &fd)) != 0) {
                __db_err(dbenv, "region open: %s: %s", name, strerror(ret));
                goto err2;
        }
@@ -225,8 +250,10 @@ __db_ropen(dbenv, appname, path, file, flags, fdp, retp)
         * flatly impossible.  Hope that mmap fails if the file is too large.
         *
         */
-       if ((ret = __db_stat(dbenv, name, fd, &size1, NULL)) != 0)
+       if ((ret = __db_ioinfo(name, fd, &size1, NULL)) != 0) {
+               __db_err(dbenv, "%s: %s", name, strerror(ret));
                goto err2;
+       }
 
        /* Check to make sure the first block has been written. */
        if ((size_t)size1 < sizeof(RLAYOUT)) {
@@ -249,16 +276,17 @@ __db_ropen(dbenv, appname, path, file, flags, fdp, retp)
 
        /* Get the region lock. */
        if (!LF_ISSET(DB_MUTEXDEBUG))
-               (void)__db_mutex_lock(&rp->lock,
-                   fd, dbenv == NULL ? NULL : dbenv->db_yield);
+               (void)__db_mutex_lock(&rp->lock, fd);
 
        /*
         * The file may have been half-written if we were descheduled between
         * getting the size of the file and checking the major version.  Check
         * to make sure we got the entire file.
         */
-       if ((ret = __db_stat(dbenv, name, fd, &size2, NULL)) != 0)
+       if ((ret = __db_ioinfo(name, fd, &size2, NULL)) != 0) {
+               __db_err(dbenv, "%s: %s", name, strerror(ret));
                goto err1;
+       }
        if (size1 != size2) {
                ret = EAGAIN;
                goto err1;
@@ -285,7 +313,7 @@ __db_ropen(dbenv, appname, path, file, flags, fdp, retp)
 err1:  if (!LF_ISSET(DB_MUTEXDEBUG))
                (void)__db_mutex_unlock(&rp->lock, fd);
 err2:  if (rp != NULL)
-               (void)__db_munmap(rp, rp->size);
+               (void)__db_unmap(rp, rp->size);
        if (fd != -1)
                (void)__db_close(fd);
        FREES(name);
@@ -312,8 +340,7 @@ __db_rclose(dbenv, fd, ptr)
        fail = NULL;
 
        /* Get the lock. */
-       if ((ret = __db_mutex_lock(&rp->lock,
-           fd, dbenv == NULL ? NULL : dbenv->db_yield)) != 0) {
+       if ((ret = __db_mutex_lock(&rp->lock, fd)) != 0) {
                fail = "lock get";
                goto err;
        }
@@ -328,7 +355,7 @@ __db_rclose(dbenv, fd, ptr)
        }
 
        /* Discard the region. */
-       if ((t_ret = __db_munmap(ptr, rp->size)) != 0 && fail == NULL) {
+       if ((t_ret = __db_unmap(ptr, rp->size)) != 0 && fail == NULL) {
                ret = t_ret;
                fail = "munmap";
        }
@@ -392,8 +419,7 @@ __db_runlink(dbenv, appname, path, file, force)
        /* Open and lock the region. */
        if ((ret = __db_ropen(dbenv, appname, path, file, 0, &fd, &rp)) != 0)
                goto err1;
-       (void)__db_mutex_lock(&rp->lock,
-           fd, dbenv == NULL ? NULL : dbenv->db_yield);
+       (void)__db_mutex_lock(&rp->lock, fd);
 
        /* If the region is currently being deleted, fail. */
        if (F_ISSET(rp, DB_R_DELETED)) {
@@ -434,8 +460,7 @@ __db_runlink(dbenv, appname, path, file, force)
        /* Not a clue.  Try to clear the DB_R_DELETED flag. */
        if ((ret = __db_ropen(dbenv, appname, path, file, 0, &fd, &rp)) != 0)
                goto err1;
-       (void)__db_mutex_lock(&rp->lock,
-           fd, dbenv == NULL ? NULL : dbenv->db_yield);
+       (void)__db_mutex_lock(&rp->lock, fd);
        F_CLR(rp, DB_R_DELETED);
        /* FALLTHROUGH */
 
@@ -472,7 +497,7 @@ __db_rgrow(dbenv, fd, incr)
        char buf[__DB_VMPAGESIZE];
 
        /* Seek to the end of the region. */
-       if ((ret = __db_lseek(fd, 0, 0, 0, SEEK_END)) != 0)
+       if ((ret = __db_seek(fd, 0, 0, 0, SEEK_END)) != 0)
                goto err;
 
        /* Write nuls to the new bytes. */
@@ -500,7 +525,7 @@ __db_rgrow(dbenv, fd, incr)
        incr -= incr % __DB_VMPAGESIZE;
 
        /* Write the last page, not the page after the last. */
-       if ((ret = __db_lseek(fd, 0, 0, incr - __DB_VMPAGESIZE, SEEK_CUR)) != 0)
+       if ((ret = __db_seek(fd, 0, 0, incr - __DB_VMPAGESIZE, SEEK_CUR)) != 0)
                goto err;
        if ((ret = __db_write(fd, buf, sizeof(buf), &nw)) != 0)
                goto err;
@@ -531,7 +556,7 @@ __db_rremap(dbenv, ptr, oldsize, newsize, fd, retp)
 {
        int ret;
 
-       if ((ret = __db_munmap(ptr, oldsize)) != 0) {
+       if ((ret = __db_unmap(ptr, oldsize)) != 0) {
                __db_err(dbenv, "region remap: munmap: %s", strerror(ret));
                return (ret);
        }
@@ -553,7 +578,7 @@ __db_rmap(dbenv, fd, size, retp)
        RLAYOUT *rp;
        int ret;
 
-       if ((ret = __db_mmap(fd, size, 0, 0, &rp)) != 0) {
+       if ((ret = __db_map(fd, size, 0, 0, (void **)&rp)) != 0) {
                __db_err(dbenv, "region map: mmap %s", strerror(ret));
                return (ret);
        }
index 6911002..fb2d6bb 100644 (file)
--- a/db2/db.h
+++ b/db2/db.h
@@ -4,7 +4,7 @@
  * Copyright (c) 1996, 1997
  *     Sleepycat Software.  All rights reserved.
  *
- *     @(#)db.h.src    10.77 (Sleepycat) 9/24/97
+ *     @(#)db.h.src    10.91 (Sleepycat) 11/3/97
  */
 
 #ifndef _DB_H_
  * XXX
  * Handle function prototypes and the keyword "const".  This steps on name
  * space that DB doesn't control, but all of the other solutions are worse.
+ *
+ * XXX
+ * While Microsoft's compiler is ANSI C compliant, it doesn't have _STDC_
+ * defined by default, you specify a command line flag or #pragma to turn
+ * it on.  Don't do that, however, because some of Microsoft's own header
+ * files won't compile.
  */
 #undef __P
-#if defined(__STDC__) || defined(__cplusplus)
+#if defined(__STDC__) || defined(__cplusplus) || defined(_MSC_VER)
 #define        __P(protos)     protos          /* ANSI C prototypes */
 #else
 #define        const
@@ -67,8 +73,8 @@
 
 #define        DB_VERSION_MAJOR        2
 #define        DB_VERSION_MINOR        3
-#define        DB_VERSION_PATCH        10
-#define        DB_VERSION_STRING       "Sleepycat Software: DB 2.3.10: (9/24/97)"
+#define        DB_VERSION_PATCH        12
+#define        DB_VERSION_STRING       "Sleepycat Software: DB 2.3.12: (11/3/97)"
 
 typedef        u_int32_t       db_pgno_t;      /* Page number type. */
 typedef        u_int16_t       db_indx_t;      /* Page offset type. */
@@ -93,6 +99,7 @@ struct __db_lockregion;       typedef struct __db_lockregion DB_LOCKREGION;
 struct __db_lockreq;   typedef struct __db_lockreq DB_LOCKREQ;
 struct __db_locktab;   typedef struct __db_locktab DB_LOCKTAB;
 struct __db_log;       typedef struct __db_log DB_LOG;
+struct __db_log_stat;  typedef struct __db_log_stat DB_LOG_STAT;
 struct __db_lsn;       typedef struct __db_lsn DB_LSN;
 struct __db_mpool;     typedef struct __db_mpool DB_MPOOL;
 struct __db_mpool_fstat;typedef struct __db_mpool_fstat DB_MPOOL_FSTAT;
@@ -122,6 +129,31 @@ struct __db_dbt {
 };
 
 /*
+ * DB configuration.  There are a set of functions which the application
+ * can replace with its own versions.
+ */
+#define        DB_FUNC_CALLOC   1              /* ANSI C calloc. */
+#define        DB_FUNC_CLOSE    2              /* POSIX 1003.1 close. */
+#define        DB_FUNC_DIRFREE  3              /* DB: free directory list. */
+#define        DB_FUNC_DIRLIST  4              /* DB: create directory list. */
+#define        DB_FUNC_EXISTS   5              /* DB: return if file exists. */
+#define        DB_FUNC_FREE     6              /* ANSI C free. */
+#define        DB_FUNC_FSYNC    7              /* POSIX 1003.1 fsync. */
+#define        DB_FUNC_IOINFO   8              /* DB: return file I/O information. */
+#define        DB_FUNC_MALLOC   9              /* ANSI C malloc. */
+#define        DB_FUNC_MAP     10              /* DB: map file into shared memory. */
+#define        DB_FUNC_OPEN    11              /* POSIX 1003.1 open. */
+#define        DB_FUNC_READ    12              /* POSIX 1003.1 read. */
+#define        DB_FUNC_REALLOC 13              /* ANSI C realloc. */
+#define        DB_FUNC_SEEK    14              /* POSIX 1003.1 lseek. */
+#define        DB_FUNC_SLEEP   15              /* DB: sleep secs/usecs. */
+#define        DB_FUNC_STRDUP  16              /* ANSI C strdup. */
+#define        DB_FUNC_UNLINK  17              /* POSIX 1003.1 unlink. */
+#define        DB_FUNC_UNMAP   18              /* DB: unmap shared memory file. */
+#define        DB_FUNC_WRITE   19              /* POSIX 1003.1 write. */
+#define        DB_FUNC_YIELD   20              /* DB: yield thread to scheduler. */
+
+/*
  * Database configuration and initialization.
  */
  /*
@@ -134,21 +166,20 @@ struct __db_dbt {
 /*
  * Flags understood by db_appinit(3).
  *
- * DB_APP_INIT and DB_MUTEXDEBUG are internal only, and not documented.
+ * DB_MUTEXDEBUG is internal only, and not documented.
  */
 /*                             0x00007    COMMON MASK. */
-#define        DB_APP_INIT             0x00008 /* Appinit called, paths initialized. */
-#define        DB_INIT_LOCK            0x00010 /* Initialize locking. */
-#define        DB_INIT_LOG             0x00020 /* Initialize logging. */
-#define        DB_INIT_MPOOL           0x00040 /* Initialize mpool. */
-#define        DB_INIT_TXN             0x00080 /* Initialize transactions. */
-#define        DB_MPOOL_PRIVATE        0x00100 /* Mpool: private memory pool. */
-#define        DB_MUTEXDEBUG           0x00200 /* Do not get/set mutexes in regions. */
-#define        DB_RECOVER              0x00400 /* Run normal recovery. */
-#define        DB_RECOVER_FATAL        0x00800 /* Run catastrophic recovery. */
-#define        DB_TXN_NOSYNC           0x01000 /* Do not sync log on commit. */
-#define        DB_USE_ENVIRON          0x02000 /* Use the environment. */
-#define        DB_USE_ENVIRON_ROOT     0x04000 /* Use the environment if root. */
+#define        DB_INIT_LOCK            0x00008 /* Initialize locking. */
+#define        DB_INIT_LOG             0x00010 /* Initialize logging. */
+#define        DB_INIT_MPOOL           0x00020 /* Initialize mpool. */
+#define        DB_INIT_TXN             0x00040 /* Initialize transactions. */
+#define        DB_MPOOL_PRIVATE        0x00080 /* Mpool: private memory pool. */
+#define        DB_MUTEXDEBUG           0x00100 /* Do not get/set mutexes in regions. */
+#define        DB_RECOVER              0x00200 /* Run normal recovery. */
+#define        DB_RECOVER_FATAL        0x00400 /* Run catastrophic recovery. */
+#define        DB_TXN_NOSYNC           0x00800 /* Do not sync log on commit. */
+#define        DB_USE_ENVIRON          0x01000 /* Use the environment. */
+#define        DB_USE_ENVIRON_ROOT     0x02000 /* Use the environment if root. */
 
 /* CURRENTLY UNUSED LOCK FLAGS. */
 #define        DB_TXN_LOCK_2PL         0x00000 /* Two-phase locking. */
@@ -209,7 +240,6 @@ struct __db_env {
        int              lk_modes;      /* Number of lock modes in table. */
        unsigned int     lk_max;        /* Maximum number of locks. */
        u_int32_t        lk_detect;     /* Deadlock detect on every conflict. */
-       int (*db_yield) __P((void));    /* Yield function for threads. */
 
        /* Logging. */
        DB_LOG          *lg_info;       /* Return from log_open(). */
@@ -226,6 +256,9 @@ struct __db_env {
        int (*tx_recover)               /* Dispatch function for recovery. */
            __P((DB_LOG *, DBT *, DB_LSN *, int, void *));
 
+#define        DB_ENV_APPINIT          0x01    /* Paths initialized by db_appinit(). */
+#define        DB_ENV_STANDALONE       0x02    /* Test: freestanding environment. */
+#define        DB_ENV_THREAD           0x04    /* DB_ENV is multi-threaded. */
        u_int32_t        flags;         /* Flags. */
 };
 
@@ -301,7 +334,7 @@ struct __db_info {
 #define        DB_CURRENT      0x000010        /* c_get(), c_put(), log_get() */
 #define        DB_FIRST        0x000020        /* c_get(), log_get() */
 #define        DB_FLUSH        0x000040        /* log_put() */
-#define        DB_GET_RECNO    0x000080        /* c_get() */
+#define        DB_GET_RECNO    0x000080        /* get(), c_get() */
 #define        DB_KEYFIRST     0x000100        /* c_put() */
 #define        DB_KEYLAST      0x000200        /* c_put() */
 #define        DB_LAST         0x000400        /* c_get(), log_get() */
@@ -312,7 +345,7 @@ struct __db_info {
 #define        DB_RECORDCOUNT  0x008000        /* stat() */
 #define        DB_SET          0x010000        /* c_get(), log_get() */
 #define        DB_SET_RANGE    0x020000        /* c_get() */
-#define        DB_SET_RECNO    0x040000        /* get(), c_get() */
+#define        DB_SET_RECNO    0x040000        /* c_get() */
 
 /* DB (user visible) error return codes. */
 #define        DB_INCOMPLETE           ( -1)   /* Sync didn't finish. */
@@ -472,6 +505,8 @@ struct __db_bt_stat {
        u_int32_t bt_get;               /* Items retrieved. */
        u_int32_t bt_cache_hit;         /* Hits in fast-insert code. */
        u_int32_t bt_cache_miss;        /* Misses in fast-insert code. */
+       u_int32_t bt_magic;             /* Magic number. */
+       u_int32_t bt_version;           /* Version number. */
 };
 
 #if defined(__cplusplus)
@@ -479,6 +514,7 @@ extern "C" {
 #endif
 int   db_appinit __P((const char *, char * const *, DB_ENV *, int));
 int   db_appexit __P((DB_ENV *));
+int   db_jump_set __P((void *, int));
 int   db_open __P((const char *, DBTYPE, int, int, DB_ENV *, DB_INFO *, DB **));
 char *db_version __P((int *, int *, int *));
 #if defined(__cplusplus)
@@ -576,6 +612,22 @@ struct __db_lsn {
        u_int32_t       offset;         /* File offset. */
 };
 
+/* Log statistics structure. */
+struct __db_log_stat {
+       u_int32_t st_magic;             /* Log file magic number. */
+       u_int32_t st_version;           /* Log file version number. */
+       int st_mode;                    /* Log file mode. */
+       u_int32_t st_lg_max;            /* Maximum log file size. */
+       u_int32_t st_w_bytes;           /* Bytes to log. */
+       u_int32_t st_w_mbytes;          /* Megabytes to log. */
+       u_int32_t st_wc_bytes;          /* Bytes to log since checkpoint. */
+       u_int32_t st_wc_mbytes;         /* Megabytes to log since checkpoint. */
+       u_int32_t st_wcount;            /* Total syncs to the log. */
+       u_int32_t st_scount;            /* Total writes to the log. */
+       u_int32_t st_region_wait;       /* Region lock granted after wait. */
+       u_int32_t st_region_nowait;     /* Region lock granted without wait. */
+};
+
 #if defined(__cplusplus)
 extern "C" {
 #endif
@@ -588,6 +640,7 @@ int  log_get __P((DB_LOG *, DB_LSN *, DBT *, int));
 int     log_open __P((const char *, int, int, DB_ENV *, DB_LOG **));
 int     log_put __P((DB_LOG *, DB_LSN *, const DBT *, int));
 int     log_register __P((DB_LOG *, DB *, const char *, DBTYPE, u_int32_t *));
+int     log_stat __P((DB_LOG *, DB_LOG_STAT **, void *(*)(size_t)));
 int     log_unlink __P((const char *, int, DB_ENV *));
 int     log_unregister __P((DB_LOG *, u_int32_t));
 #if defined(__cplusplus)
@@ -610,30 +663,35 @@ int        log_unregister __P((DB_LOG *, u_int32_t));
 /* Mpool statistics structure. */
 struct __db_mpool_stat {
        size_t st_cachesize;            /* Cache size. */
-       unsigned long st_cache_hit;     /* Pages found in the cache. */
-       unsigned long st_cache_miss;    /* Pages not found in the cache. */
-       unsigned long st_map;           /* Pages from mapped files. */
-       unsigned long st_page_create;   /* Pages created in the cache. */
-       unsigned long st_page_in;       /* Pages read in. */
-       unsigned long st_page_out;      /* Pages written out. */
-       unsigned long st_ro_evict;      /* Read-only pages evicted. */
-       unsigned long st_rw_evict;      /* Read-write pages evicted. */
-       unsigned long st_hash_buckets;  /* Number of hash buckets. */
-       unsigned long st_hash_searches; /* Total hash chain searches. */
-       unsigned long st_hash_longest;  /* Longest hash chain searched. */
-       unsigned long st_hash_examined; /* Total hash entries searched. */
+       u_int32_t st_cache_hit;         /* Pages found in the cache. */
+       u_int32_t st_cache_miss;        /* Pages not found in the cache. */
+       u_int32_t st_map;               /* Pages from mapped files. */
+       u_int32_t st_page_create;       /* Pages created in the cache. */
+       u_int32_t st_page_in;           /* Pages read in. */
+       u_int32_t st_page_out;          /* Pages written out. */
+       u_int32_t st_ro_evict;          /* Clean pages forced from the cache. */
+       u_int32_t st_rw_evict;          /* Dirty pages forced from the cache. */
+       u_int32_t st_hash_buckets;      /* Number of hash buckets. */
+       u_int32_t st_hash_searches;     /* Total hash chain searches. */
+       u_int32_t st_hash_longest;      /* Longest hash chain searched. */
+       u_int32_t st_hash_examined;     /* Total hash entries searched. */
+       u_int32_t st_page_clean;        /* Clean pages. */
+       u_int32_t st_page_dirty;        /* Dirty pages. */
+       u_int32_t st_page_trickle;      /* Pages written by memp_trickle. */
+       u_int32_t st_region_wait;       /* Region lock granted after wait. */
+       u_int32_t st_region_nowait;     /* Region lock granted without wait. */
 };
 
 /* Mpool file statistics structure. */
 struct __db_mpool_fstat {
        char *file_name;                /* File name. */
        size_t st_pagesize;             /* Page size. */
-       unsigned long st_cache_hit;     /* Pages found in the cache. */
-       unsigned long st_cache_miss;    /* Pages not found in the cache. */
-       unsigned long st_map;           /* Pages from mapped files. */
-       unsigned long st_page_create;   /* Pages created in the cache. */
-       unsigned long st_page_in;       /* Pages read in. */
-       unsigned long st_page_out;      /* Pages written out. */
+       u_int32_t st_cache_hit;         /* Pages found in the cache. */
+       u_int32_t st_cache_miss;        /* Pages not found in the cache. */
+       u_int32_t st_map;               /* Pages from mapped files. */
+       u_int32_t st_page_create;       /* Pages created in the cache. */
+       u_int32_t st_page_in;           /* Pages read in. */
+       u_int32_t st_page_out;          /* Pages written out. */
 };
 
 #if defined(__cplusplus)
@@ -654,6 +712,7 @@ int memp_register __P((DB_MPOOL *, int,
 int    memp_stat __P((DB_MPOOL *,
            DB_MPOOL_STAT **, DB_MPOOL_FSTAT ***, void *(*)(size_t)));
 int    memp_sync __P((DB_MPOOL *, DB_LSN *));
+int    memp_trickle __P((DB_MPOOL *, int, int *));
 int    memp_unlink __P((const char *, int, DB_ENV *));
 #if defined(__cplusplus)
 };
index 9ebe73c..50b14eb 100644 (file)
@@ -44,7 +44,7 @@
 #include "config.h"
 
 #ifndef lint
-static const char sccsid[] = "@(#)db.c 10.41 (Sleepycat) 9/23/97";
+static const char sccsid[] = "@(#)db.c 10.44 (Sleepycat) 10/25/97";
 #endif /* not lint */
 
 #ifndef NO_SYSTEM_INCLUDES
@@ -125,13 +125,19 @@ db_open(fname, type, flags, mode, dbenv, dbinfo, dbpp)
        if ((ret = __db_fchk(dbenv, "db_open", flags, OKFLAGS)) != 0)
                return (ret);
 
+       if (dbenv != NULL &&
+           LF_ISSET(DB_THREAD) && !F_ISSET(dbenv, DB_ENV_THREAD)) {
+               __db_err(dbenv, "environment not created using DB_THREAD");
+               return (EINVAL);
+       }
+
        /* Initialize for error return. */
        fd = -1;
        need_fileid = 1;
        real_name = NULL;
 
        /* Allocate the DB structure, reference the DB_ENV structure. */
-       if ((dbp = (DB *)calloc(1, sizeof(DB))) == NULL) {
+       if ((dbp = (DB *)__db_calloc(1, sizeof(DB))) == NULL) {
                __db_err(dbenv, "%s", strerror(ENOMEM));
                return (ENOMEM);
        }
@@ -239,7 +245,7 @@ db_open(fname, type, flags, mode, dbenv, dbinfo, dbpp)
                 */
                retry_cnt = 0;
 open_retry:    if (LF_ISSET(DB_CREATE)) {
-                       if ((ret = __db_fdopen(real_name, flags | DB_EXCL,
+                       if ((ret = __db_open(real_name, flags | DB_EXCL,
                            OKFLAGS | DB_EXCL, mode, &fd)) != 0)
                                if (ret == EEXIST) {
                                        LF_CLR(DB_CREATE);
@@ -250,7 +256,7 @@ open_retry: if (LF_ISSET(DB_CREATE)) {
                                        goto err;
                                }
                } else
-                       if ((ret = __db_fdopen(real_name,
+                       if ((ret = __db_open(real_name,
                            flags, OKFLAGS, mode, &fd)) != 0) {
                                __db_err(dbenv, "%s: %s", fname, strerror(ret));
                                goto err;
@@ -264,8 +270,11 @@ open_retry:        if (LF_ISSET(DB_CREATE)) {
                 */
                if (dbp->pgsize == 0) {
                        if ((ret =
-                           __db_stat(dbenv, real_name, fd, NULL, &io)) != 0)
+                           __db_ioinfo(real_name, fd, NULL, &io)) != 0) {
+                               __db_err(dbenv,
+                                   "%s: %s", real_name, strerror(ret));
                                goto err;
+                       }
                        if (io < 512)
                                io = 512;
                        if (io > 16 * 1024)
@@ -477,7 +486,7 @@ empty:      /*
 
                if (dbenv == NULL) {
                        if ((dbp->mp_dbenv =
-                           (DB_ENV *)calloc(sizeof(DB_ENV), 1)) == NULL) {
+                           (DB_ENV *)__db_calloc(sizeof(DB_ENV), 1)) == NULL) {
                                ret = ENOMEM;
                                goto err;
                        }
@@ -491,9 +500,9 @@ empty:      /*
                        restore = 1;
                }
                envp->mp_size = cachesize;
-               F_SET(envp, DB_MPOOL_PRIVATE);
-               if ((ret = memp_open(NULL,
-                   DB_CREATE, S_IRUSR | S_IWUSR, envp, &dbp->mp)) != 0)
+               if ((ret = memp_open(NULL, DB_CREATE | DB_MPOOL_PRIVATE |
+                   (F_ISSET(dbp, DB_AM_THREAD) ? DB_THREAD : 0),
+                   S_IRUSR | S_IWUSR, envp, &dbp->mp)) != 0)
                        goto err;
                if (restore)
                        *dbenv = t_dbenv;
@@ -725,7 +734,8 @@ db_close(dbp, flags)
        }
 
        /* Sync the memory pool. */
-       if ((t_ret = memp_fsync(dbp->mpf)) != 0 && ret == 0)
+       if ((t_ret = memp_fsync(dbp->mpf)) != 0 &&
+           t_ret != DB_INCOMPLETE && ret == 0)
                ret = t_ret;
 
        /* Close the memory pool file. */
index a3e2f7b..07d9812 100644 (file)
@@ -3,7 +3,7 @@
  *
  * Copyright (c) 1996, 1997
  *     Sleepycat Software.  All rights reserved.
- *     @(#)db.src      10.3 (Sleepycat) 8/18/97
+ *     @(#)db.src      10.4 (Sleepycat) 11/2/97
  */
 #include "config.h"
 
@@ -81,15 +81,17 @@ POINTER     nextlsn         DB_LSN *        lu
 END
 
 /*
- * ovref -- Handles increment of overflow page reference count.
+ * ovref -- Handles increment/decrement of overflow page reference count.
  *
  * fileid:     identifies the file being modified.
- * pgno:       page number being incremented.
- * lsn         the page's original lsn.
+ * pgno:       page number whose ref count is being incremented/decremented.
+ * adjust:     the adjustment being made.
+ * lsn:                the page's original lsn.
  */
 BEGIN ovref
 ARG    fileid          u_int32_t       lu
 ARG    pgno            db_pgno_t       lu
+ARG    adjust          int32_t         ld
 POINTER        lsn             DB_LSN *        lu
 END
 
index 6922504..d40d964 100644 (file)
@@ -62,7 +62,7 @@ int __db_addrem_log(logp, txnid, ret_lsnp, flags,
            + sizeof(u_int32_t) + (hdr == NULL ? 0 : hdr->size)
            + sizeof(u_int32_t) + (dbt == NULL ? 0 : dbt->size)
            + sizeof(*pagelsn);
-       if ((logrec.data = (void *)malloc(logrec.size)) == NULL)
+       if ((logrec.data = (void *)__db_malloc(logrec.size)) == NULL)
                return (ENOMEM);
 
        bp = logrec.data;
@@ -114,7 +114,7 @@ int __db_addrem_log(logp, txnid, ret_lsnp, flags,
        ret = log_put(logp, ret_lsnp, (DBT *)&logrec, flags);
        if (txnid != NULL)
                txnid->last_lsn = *ret_lsnp;
-       free(logrec.data);
+       __db_free(logrec.data);
        return (ret);
 }
 
@@ -176,7 +176,7 @@ __db_addrem_print(notused1, dbtp, lsnp, notused3, notused4)
        printf("\tpagelsn: [%lu][%lu]\n",
            (u_long)argp->pagelsn.file, (u_long)argp->pagelsn.offset);
        printf("\n");
-       free(argp);
+       __db_free(argp);
        return (0);
 }
 
@@ -191,7 +191,7 @@ __db_addrem_read(recbuf, argpp)
        __db_addrem_args *argp;
        u_int8_t *bp;
 
-       argp = (__db_addrem_args *)malloc(sizeof(__db_addrem_args) +
+       argp = (__db_addrem_args *)__db_malloc(sizeof(__db_addrem_args) +
            sizeof(DB_TXN));
        if (argp == NULL)
                return (ENOMEM);
@@ -266,7 +266,7 @@ int __db_split_log(logp, txnid, ret_lsnp, flags,
            + sizeof(pgno)
            + sizeof(u_int32_t) + (pageimage == NULL ? 0 : pageimage->size)
            + sizeof(*pagelsn);
-       if ((logrec.data = (void *)malloc(logrec.size)) == NULL)
+       if ((logrec.data = (void *)__db_malloc(logrec.size)) == NULL)
                return (ENOMEM);
 
        bp = logrec.data;
@@ -304,7 +304,7 @@ int __db_split_log(logp, txnid, ret_lsnp, flags,
        ret = log_put(logp, ret_lsnp, (DBT *)&logrec, flags);
        if (txnid != NULL)
                txnid->last_lsn = *ret_lsnp;
-       free(logrec.data);
+       __db_free(logrec.data);
        return (ret);
 }
 
@@ -355,7 +355,7 @@ __db_split_print(notused1, dbtp, lsnp, notused3, notused4)
        printf("\tpagelsn: [%lu][%lu]\n",
            (u_long)argp->pagelsn.file, (u_long)argp->pagelsn.offset);
        printf("\n");
-       free(argp);
+       __db_free(argp);
        return (0);
 }
 
@@ -370,7 +370,7 @@ __db_split_read(recbuf, argpp)
        __db_split_args *argp;
        u_int8_t *bp;
 
-       argp = (__db_split_args *)malloc(sizeof(__db_split_args) +
+       argp = (__db_split_args *)__db_malloc(sizeof(__db_split_args) +
            sizeof(DB_TXN));
        if (argp == NULL)
                return (ENOMEM);
@@ -447,7 +447,7 @@ int __db_big_log(logp, txnid, ret_lsnp, flags,
            + sizeof(*pagelsn)
            + sizeof(*prevlsn)
            + sizeof(*nextlsn);
-       if ((logrec.data = (void *)malloc(logrec.size)) == NULL)
+       if ((logrec.data = (void *)__db_malloc(logrec.size)) == NULL)
                return (ENOMEM);
 
        bp = logrec.data;
@@ -499,7 +499,7 @@ int __db_big_log(logp, txnid, ret_lsnp, flags,
        ret = log_put(logp, ret_lsnp, (DBT *)&logrec, flags);
        if (txnid != NULL)
                txnid->last_lsn = *ret_lsnp;
-       free(logrec.data);
+       __db_free(logrec.data);
        return (ret);
 }
 
@@ -556,7 +556,7 @@ __db_big_print(notused1, dbtp, lsnp, notused3, notused4)
        printf("\tnextlsn: [%lu][%lu]\n",
            (u_long)argp->nextlsn.file, (u_long)argp->nextlsn.offset);
        printf("\n");
-       free(argp);
+       __db_free(argp);
        return (0);
 }
 
@@ -571,7 +571,7 @@ __db_big_read(recbuf, argpp)
        __db_big_args *argp;
        u_int8_t *bp;
 
-       argp = (__db_big_args *)malloc(sizeof(__db_big_args) +
+       argp = (__db_big_args *)__db_malloc(sizeof(__db_big_args) +
            sizeof(DB_TXN));
        if (argp == NULL)
                return (ENOMEM);
@@ -610,16 +610,17 @@ __db_big_read(recbuf, argpp)
 /*
  * PUBLIC: int __db_ovref_log
  * PUBLIC:     __P((DB_LOG *, DB_TXN *, DB_LSN *, u_int32_t,
- * PUBLIC:     u_int32_t, db_pgno_t, DB_LSN *));
+ * PUBLIC:     u_int32_t, db_pgno_t, int32_t, DB_LSN *));
  */
 int __db_ovref_log(logp, txnid, ret_lsnp, flags,
-       fileid, pgno, lsn)
+       fileid, pgno, adjust, lsn)
        DB_LOG *logp;
        DB_TXN *txnid;
        DB_LSN *ret_lsnp;
        u_int32_t flags;
        u_int32_t fileid;
        db_pgno_t pgno;
+       int32_t adjust;
        DB_LSN * lsn;
 {
        DBT logrec;
@@ -639,8 +640,9 @@ int __db_ovref_log(logp, txnid, ret_lsnp, flags,
        logrec.size = sizeof(rectype) + sizeof(txn_num) + sizeof(DB_LSN)
            + sizeof(fileid)
            + sizeof(pgno)
+           + sizeof(adjust)
            + sizeof(*lsn);
-       if ((logrec.data = (void *)malloc(logrec.size)) == NULL)
+       if ((logrec.data = (void *)__db_malloc(logrec.size)) == NULL)
                return (ENOMEM);
 
        bp = logrec.data;
@@ -654,6 +656,8 @@ int __db_ovref_log(logp, txnid, ret_lsnp, flags,
        bp += sizeof(fileid);
        memcpy(bp, &pgno, sizeof(pgno));
        bp += sizeof(pgno);
+       memcpy(bp, &adjust, sizeof(adjust));
+       bp += sizeof(adjust);
        if (lsn != NULL)
                memcpy(bp, lsn, sizeof(*lsn));
        else
@@ -666,7 +670,7 @@ int __db_ovref_log(logp, txnid, ret_lsnp, flags,
        ret = log_put(logp, ret_lsnp, (DBT *)&logrec, flags);
        if (txnid != NULL)
                txnid->last_lsn = *ret_lsnp;
-       free(logrec.data);
+       __db_free(logrec.data);
        return (ret);
 }
 
@@ -704,10 +708,11 @@ __db_ovref_print(notused1, dbtp, lsnp, notused3, notused4)
            (u_long)argp->prev_lsn.offset);
        printf("\tfileid: %lu\n", (u_long)argp->fileid);
        printf("\tpgno: %lu\n", (u_long)argp->pgno);
+       printf("\tadjust: %ld\n", (long)argp->adjust);
        printf("\tlsn: [%lu][%lu]\n",
            (u_long)argp->lsn.file, (u_long)argp->lsn.offset);
        printf("\n");
-       free(argp);
+       __db_free(argp);
        return (0);
 }
 
@@ -722,7 +727,7 @@ __db_ovref_read(recbuf, argpp)
        __db_ovref_args *argp;
        u_int8_t *bp;
 
-       argp = (__db_ovref_args *)malloc(sizeof(__db_ovref_args) +
+       argp = (__db_ovref_args *)__db_malloc(sizeof(__db_ovref_args) +
            sizeof(DB_TXN));
        if (argp == NULL)
                return (ENOMEM);
@@ -738,6 +743,8 @@ __db_ovref_read(recbuf, argpp)
        bp += sizeof(argp->fileid);
        memcpy(&argp->pgno, bp, sizeof(argp->pgno));
        bp += sizeof(argp->pgno);
+       memcpy(&argp->adjust, bp, sizeof(argp->adjust));
+       bp += sizeof(argp->adjust);
        memcpy(&argp->lsn, bp,  sizeof(argp->lsn));
        bp += sizeof(argp->lsn);
        *argpp = argp;
@@ -787,7 +794,7 @@ int __db_relink_log(logp, txnid, ret_lsnp, flags,
            + sizeof(*lsn_prev)
            + sizeof(next)
            + sizeof(*lsn_next);
-       if ((logrec.data = (void *)malloc(logrec.size)) == NULL)
+       if ((logrec.data = (void *)__db_malloc(logrec.size)) == NULL)
                return (ENOMEM);
 
        bp = logrec.data;
@@ -827,7 +834,7 @@ int __db_relink_log(logp, txnid, ret_lsnp, flags,
        ret = log_put(logp, ret_lsnp, (DBT *)&logrec, flags);
        if (txnid != NULL)
                txnid->last_lsn = *ret_lsnp;
-       free(logrec.data);
+       __db_free(logrec.data);
        return (ret);
 }
 
@@ -874,7 +881,7 @@ __db_relink_print(notused1, dbtp, lsnp, notused3, notused4)
        printf("\tlsn_next: [%lu][%lu]\n",
            (u_long)argp->lsn_next.file, (u_long)argp->lsn_next.offset);
        printf("\n");
-       free(argp);
+       __db_free(argp);
        return (0);
 }
 
@@ -889,7 +896,7 @@ __db_relink_read(recbuf, argpp)
        __db_relink_args *argp;
        u_int8_t *bp;
 
-       argp = (__db_relink_args *)malloc(sizeof(__db_relink_args) +
+       argp = (__db_relink_args *)__db_malloc(sizeof(__db_relink_args) +
            sizeof(DB_TXN));
        if (argp == NULL)
                return (ENOMEM);
@@ -957,7 +964,7 @@ int __db_addpage_log(logp, txnid, ret_lsnp, flags,
            + sizeof(*lsn)
            + sizeof(nextpgno)
            + sizeof(*nextlsn);
-       if ((logrec.data = (void *)malloc(logrec.size)) == NULL)
+       if ((logrec.data = (void *)__db_malloc(logrec.size)) == NULL)
                return (ENOMEM);
 
        bp = logrec.data;
@@ -990,7 +997,7 @@ int __db_addpage_log(logp, txnid, ret_lsnp, flags,
        ret = log_put(logp, ret_lsnp, (DBT *)&logrec, flags);
        if (txnid != NULL)
                txnid->last_lsn = *ret_lsnp;
-       free(logrec.data);
+       __db_free(logrec.data);
        return (ret);
 }
 
@@ -1034,7 +1041,7 @@ __db_addpage_print(notused1, dbtp, lsnp, notused3, notused4)
        printf("\tnextlsn: [%lu][%lu]\n",
            (u_long)argp->nextlsn.file, (u_long)argp->nextlsn.offset);
        printf("\n");
-       free(argp);
+       __db_free(argp);
        return (0);
 }
 
@@ -1049,7 +1056,7 @@ __db_addpage_read(recbuf, argpp)
        __db_addpage_args *argp;
        u_int8_t *bp;
 
-       argp = (__db_addpage_args *)malloc(sizeof(__db_addpage_args) +
+       argp = (__db_addpage_args *)__db_malloc(sizeof(__db_addpage_args) +
            sizeof(DB_TXN));
        if (argp == NULL)
                return (ENOMEM);
@@ -1114,7 +1121,7 @@ int __db_debug_log(logp, txnid, ret_lsnp, flags,
            + sizeof(u_int32_t) + (key == NULL ? 0 : key->size)
            + sizeof(u_int32_t) + (data == NULL ? 0 : data->size)
            + sizeof(arg_flags);
-       if ((logrec.data = (void *)malloc(logrec.size)) == NULL)
+       if ((logrec.data = (void *)__db_malloc(logrec.size)) == NULL)
                return (ENOMEM);
 
        bp = logrec.data;
@@ -1165,7 +1172,7 @@ int __db_debug_log(logp, txnid, ret_lsnp, flags,
        ret = log_put(logp, ret_lsnp, (DBT *)&logrec, flags);
        if (txnid != NULL)
                txnid->last_lsn = *ret_lsnp;
-       free(logrec.data);
+       __db_free(logrec.data);
        return (ret);
 }
 
@@ -1231,7 +1238,7 @@ __db_debug_print(notused1, dbtp, lsnp, notused3, notused4)
        printf("\n");
        printf("\targ_flags: %lu\n", (u_long)argp->arg_flags);
        printf("\n");
-       free(argp);
+       __db_free(argp);
        return (0);
 }
 
@@ -1246,7 +1253,7 @@ __db_debug_read(recbuf, argpp)
        __db_debug_args *argp;
        u_int8_t *bp;
 
-       argp = (__db_debug_args *)malloc(sizeof(__db_debug_args) +
+       argp = (__db_debug_args *)__db_malloc(sizeof(__db_debug_args) +
            sizeof(DB_TXN));
        if (argp == NULL)
                return (ENOMEM);
@@ -1303,7 +1310,7 @@ int __db_noop_log(logp, txnid, ret_lsnp, flags)
        } else
                lsnp = &txnid->last_lsn;
        logrec.size = sizeof(rectype) + sizeof(txn_num) + sizeof(DB_LSN);
-       if ((logrec.data = (void *)malloc(logrec.size)) == NULL)
+       if ((logrec.data = (void *)__db_malloc(logrec.size)) == NULL)
                return (ENOMEM);
 
        bp = logrec.data;
@@ -1320,7 +1327,7 @@ int __db_noop_log(logp, txnid, ret_lsnp, flags)
        ret = log_put(logp, ret_lsnp, (DBT *)&logrec, flags);
        if (txnid != NULL)
                txnid->last_lsn = *ret_lsnp;
-       free(logrec.data);
+       __db_free(logrec.data);
        return (ret);
 }
 
@@ -1357,7 +1364,7 @@ __db_noop_print(notused1, dbtp, lsnp, notused3, notused4)
            (u_long)argp->prev_lsn.file,
            (u_long)argp->prev_lsn.offset);
        printf("\n");
-       free(argp);
+       __db_free(argp);
        return (0);
 }
 
@@ -1372,7 +1379,7 @@ __db_noop_read(recbuf, argpp)
        __db_noop_args *argp;
        u_int8_t *bp;
 
-       argp = (__db_noop_args *)malloc(sizeof(__db_noop_args) +
+       argp = (__db_noop_args *)__db_malloc(sizeof(__db_noop_args) +
            sizeof(DB_TXN));
        if (argp == NULL)
                return (ENOMEM);
index 3d7b162..a4bcdb7 100644 (file)
@@ -43,7 +43,7 @@
 #include "config.h"
 
 #ifndef lint
-static const char sccsid[] = "@(#)db_dispatch.c        10.5 (Sleepycat) 7/2/97";
+static const char sccsid[] = "@(#)db_dispatch.c        10.6 (Sleepycat) 10/25/97";
 #endif /* not lint */
 
 #ifndef NO_SYSTEM_INCLUDES
@@ -155,12 +155,12 @@ __db_add_recovery(dbenv, func, ndx)
        if (ndx >= dispatch_size) {
                if (dispatch_table == NULL)
                        dispatch_table = (int (**)
-                           __P((DB_LOG *, DBT *, DB_LSN *, int, void *)))
-                           malloc(DB_user_BEGIN * sizeof(dispatch_table[0]));
+                        __P((DB_LOG *, DBT *, DB_LSN *, int, void *)))
+                        __db_malloc(DB_user_BEGIN * sizeof(dispatch_table[0]));
                else
                        dispatch_table = (int (**)
                            __P((DB_LOG *, DBT *, DB_LSN *, int, void *)))
-                           realloc(dispatch_table, (DB_user_BEGIN +
+                           __db_realloc(dispatch_table, (DB_user_BEGIN +
                            dispatch_size) * sizeof(dispatch_table[0]));
                if (dispatch_table == NULL) {
                        __db_err(dbenv, "%s", strerror(ENOMEM));
@@ -187,8 +187,8 @@ __db_txnlist_init(retp)
 {
        __db_txnhead *headp;
 
-       if ((headp =
-           (struct __db_txnhead *)malloc(sizeof(struct __db_txnhead))) == NULL)
+       if ((headp = (struct __db_txnhead *)
+           __db_malloc(sizeof(struct __db_txnhead))) == NULL)
                return (ENOMEM);
 
        LIST_INIT(&headp->head);
@@ -212,7 +212,7 @@ __db_txnlist_add(listp, txnid)
        __db_txnhead *hp;
        __db_txnlist *elp;
 
-       if ((elp = (__db_txnlist *)malloc(sizeof(__db_txnlist))) == NULL)
+       if ((elp = (__db_txnlist *)__db_malloc(sizeof(__db_txnlist))) == NULL)
                return (ENOMEM);
 
        elp->txnid = txnid;
index 66c6c26..faeefa0 100644 (file)
@@ -8,7 +8,7 @@
 #include "config.h"
 
 #ifndef lint
-static const char sccsid[] = "@(#)db_dup.c     10.9 (Sleepycat) 9/3/97";
+static const char sccsid[] = "@(#)db_dup.c     10.10 (Sleepycat) 10/25/97";
 #endif /* not lint */
 
 #ifndef NO_SYSTEM_INCLUDES
@@ -217,7 +217,7 @@ __db_dsplit(dbp, hp, indxp, size, newfunc)
        indx = *indxp;
 
        /* Create a temporary page to do compaction onto. */
-       if ((tp = (PAGE *)malloc(dbp->pgsize)) == NULL)
+       if ((tp = (PAGE *)__db_malloc(dbp->pgsize)) == NULL)
                return (ENOMEM);
 #ifdef DEBUG
        memset(tp, 0xff, dbp->pgsize);
index 2340e9e..8c6619f 100644 (file)
@@ -47,7 +47,7 @@
 #include "config.h"
 
 #ifndef lint
-static const char sccsid[] = "@(#)db_overflow.c        10.4 (Sleepycat) 7/2/97";
+static const char sccsid[] = "@(#)db_overflow.c        10.7 (Sleepycat) 11/2/97";
 #endif /* not lint */
 
 #ifndef NO_SYSTEM_INCLUDES
@@ -121,14 +121,14 @@ __db_goff(dbp, dbt, tlen, pgno, bpp, bpsz)
                }
        } else if (F_ISSET(dbt, DB_DBT_MALLOC)) {
                dbt->data = dbp->db_malloc == NULL ?
-                   (void *)malloc(needed + 1) :
+                   (void *)__db_malloc(needed + 1) :
                    (void *)dbp->db_malloc(needed + 1);
                if (dbt->data == NULL)
                        return (ENOMEM);
        } else if (*bpsz == 0 || *bpsz < needed) {
                *bpp = (*bpp == NULL ?
-                   (void *)malloc(needed + 1) :
-                   (void *)realloc(*bpp, needed + 1));
+                   (void *)__db_malloc(needed + 1) :
+                   (void *)__db_realloc(*bpp, needed + 1));
                if (*bpp == NULL)
                        return (ENOMEM);
                *bpsz = needed + 1;
@@ -256,15 +256,16 @@ __db_poff(dbp, dbt, pgnop, newfunc)
 }
 
 /*
- * __db_ioff --
- *     Increment the reference count on an overflow page.
+ * __db_ovref --
+ *     Increment/decrement the reference count on an overflow page.
  *
- * PUBLIC: int __db_ioff __P((DB *, db_pgno_t));
+ * PUBLIC: int __db_ovref __P((DB *, db_pgno_t, int));
  */
 int
-__db_ioff(dbp, pgno)
+__db_ovref(dbp, pgno, adjust)
        DB *dbp;
        db_pgno_t pgno;
+       int adjust;
 {
        PAGE *h;
        int ret;
@@ -274,10 +275,12 @@ __db_ioff(dbp, pgno)
                return (ret);
        }
 
-       ++OV_REF(h);
-       if (DB_LOGGING(dbp) && (ret = __db_ovref_log(dbp->dbenv->lg_info,
-           dbp->txn, &LSN(h), 0, dbp->log_fileid, h->pgno, &LSN(h))) != 0)
-               return (ret);
+       if (DB_LOGGING(dbp))
+               if ((ret = __db_ovref_log(dbp->dbenv->lg_info, dbp->txn,
+                   &LSN(h), 0, dbp->log_fileid, h->pgno, (int32_t)adjust,
+                   &LSN(h))) != 0)
+                       return (ret);
+       OV_REF(h) += adjust;
 
        (void)memp_fput(dbp->mpf, h, DB_MPOOL_DIRTY);
        return (0);
@@ -311,9 +314,8 @@ __db_doff(dbp, pgno, freefunc)
                 * one key/data item, decrement the reference count and return.
                 */
                if (TYPE(pagep) == P_OVERFLOW && OV_REF(pagep) > 1) {
-                       --OV_REF(pagep);
-                       (void)memp_fput(dbp->mpf, pagep, DB_MPOOL_DIRTY);
-                       return (0);
+                       (void)memp_fput(dbp->mpf, pagep, 0);
+                       return (__db_ovref(dbp, pgno, -1));
                }
 
                if (DB_LOGGING(dbp)) {
index 09d8057..6b6171a 100644 (file)
@@ -8,7 +8,7 @@
 #include "config.h"
 
 #ifndef lint
-static const char sccsid[] = "@(#)db_pr.c      10.17 (Sleepycat) 9/15/97";
+static const char sccsid[] = "@(#)db_pr.c      10.19 (Sleepycat) 11/2/97";
 #endif /* not lint */
 
 #ifndef NO_SYSTEM_INCLUDES
@@ -183,7 +183,6 @@ __db_prbtree(dbp)
        };
        BTMETA *mp;
        BTREE *t;
-       DB_LOCK lock;
        EPG *epg;
        FILE *fp;
        RECNO *rp;
@@ -195,8 +194,6 @@ __db_prbtree(dbp)
 
        (void)fprintf(fp, "%s\nOn-page metadata:\n", DB_LINE);
        i = PGNO_METADATA;
-       if ((ret = __bam_lget(dbp, 0, PGNO_METADATA, DB_LOCK_READ, &lock)) != 0)
-               return (ret);
 
        if ((ret = __bam_pget(dbp, (PAGE **)&mp, &i, 0)) != 0)
                return (ret);
@@ -211,7 +208,6 @@ __db_prbtree(dbp)
        __db_prflags(mp->flags, mfn);
        (void)fprintf(fp, "\n");
        (void)memp_fput(dbp->mpf, mp, 0);
-       (void)__bam_lput(dbp, lock);
 
        (void)fprintf(fp, "%s\nDB_INFO:\n", DB_LINE);
        (void)fprintf(fp, "bt_maxkey: %lu bt_minkey: %lu\n",
@@ -416,7 +412,8 @@ __db_prpage(h, all)
            (TYPE(h) == P_LRECNO && h->pgno == PGNO_ROOT))
                fprintf(fp, " total records: %4lu", (u_long)RE_NREC(h));
        fprintf(fp, "\n");
-       if (TYPE(h) == P_LBTREE || TYPE(h) == P_LRECNO)
+       if (TYPE(h) == P_LBTREE || TYPE(h) == P_LRECNO ||
+           TYPE(h) == P_DUPLICATE || TYPE(h) == P_OVERFLOW)
                fprintf(fp, "    prev: %4lu next: %4lu",
                    (u_long)PREV_PGNO(h), (u_long)NEXT_PGNO(h));
        if (TYPE(h) == P_IBTREE || TYPE(h) == P_LBTREE)
index 900b0ed..2c9ca9a 100644 (file)
@@ -8,7 +8,7 @@
 #include "config.h"
 
 #ifndef lint
-static const char sccsid[] = "@(#)db_rec.c     10.8 (Sleepycat) 8/22/97";
+static const char sccsid[] = "@(#)db_rec.c     10.10 (Sleepycat) 11/2/97";
 #endif /* not lint */
 
 #ifndef NO_SYSTEM_INCLUDES
@@ -330,7 +330,7 @@ out:        REC_CLOSE;
 
 /*
  * __db_ovref_recover --
- *     Recovery function for __db_ioff().
+ *     Recovery function for __db_ovref().
  *
  * PUBLIC: int __db_ovref_recover __P((DB_LOG *, DBT *, DB_LSN *, int, void *));
  */
@@ -357,22 +357,21 @@ __db_ovref_recover(logp, dbtp, lsnp, redo, info)
        }
 
        modified = 0;
-       if (log_compare(lsnp, &argp->lsn) == 0 && redo) {
+       if (log_compare(&LSN(pagep), &argp->lsn) == 0 && redo) {
                /* Need to redo update described. */
-               ++OV_REF(pagep);
+               OV_REF(pagep) += argp->adjust;
 
                pagep->lsn = *lsnp;
                modified = 1;
        } else if (log_compare(lsnp, &LSN(pagep)) == 0 && !redo) {
                /* Need to undo update described. */
-               --OV_REF(pagep);
+               OV_REF(pagep) -= argp->adjust;
 
                pagep->lsn = argp->lsn;
                modified = 1;
        }
-       ret = memp_fput(mpf, pagep, modified ? DB_MPOOL_DIRTY : 0);
-
-       *lsnp = argp->prev_lsn;
+       if ((ret = memp_fput(mpf, pagep, modified ? DB_MPOOL_DIRTY : 0)) == 0)
+               *lsnp = argp->prev_lsn;
 
 out:   REC_CLOSE;
 }
@@ -413,7 +412,7 @@ __db_relink_recover(logp, dbtp, lsnp, redo, info)
                goto next;
        }
        modified = 0;
-       if (log_compare(lsnp, &argp->lsn) == 0 && redo) {
+       if (log_compare(&LSN(pagep), &argp->lsn) == 0 && redo) {
                /* Redo the relink. */
                pagep->lsn = *lsnp;
                modified = 1;
@@ -438,7 +437,7 @@ next:       if ((ret = memp_fget(mpf, &argp->next, 0, &pagep)) != 0) {
                goto prev;
        }
        modified = 0;
-       if (log_compare(lsnp, &argp->lsn_next) == 0 && redo) {
+       if (log_compare(&LSN(pagep), &argp->lsn_next) == 0 && redo) {
                /* Redo the relink. */
                pagep->prev_pgno = argp->prev;
 
@@ -464,7 +463,7 @@ prev:       if ((ret = memp_fget(mpf, &argp->prev, 0, &pagep)) != 0) {
                goto done;
        }
        modified = 0;
-       if (log_compare(lsnp, &argp->lsn_prev) == 0 && redo) {
+       if (log_compare(&LSN(pagep), &argp->lsn_prev) == 0 && redo) {
                /* Redo the relink. */
                pagep->next_pgno = argp->next;
 
index ee2bc82..bcec308 100644 (file)
@@ -8,7 +8,7 @@
 #include "config.h"
 
 #ifndef lint
-static const char sccsid[] = "@(#)db_ret.c     10.7 (Sleepycat) 9/15/97";
+static const char sccsid[] = "@(#)db_ret.c     10.8 (Sleepycat) 10/25/97";
 #endif /* not lint */
 
 #ifndef NO_SYSTEM_INCLUDES
@@ -122,7 +122,7 @@ __db_retcopy(dbt, data, len, memp, memsize, db_malloc)
         */
        if (F_ISSET(dbt, DB_DBT_MALLOC)) {
                dbt->data = db_malloc == NULL ?
-                   (void *)malloc(len + 1) :
+                   (void *)__db_malloc(len + 1) :
                    (void *)db_malloc(len + 1);
                if (dbt->data == NULL)
                        return (ENOMEM);
@@ -134,8 +134,8 @@ __db_retcopy(dbt, data, len, memp, memsize, db_malloc)
        } else {
                if (*memsize == 0 || *memsize < len) {
                        *memp = *memp == NULL ?
-                           (void *)malloc(len + 1) :
-                           (void *)realloc(*memp, len + 1);
+                           (void *)__db_malloc(len + 1) :
+                           (void *)__db_realloc(*memp, len + 1);
                        if (*memp == NULL) {
                                *memsize = 0;
                                return (ENOMEM);
index 170baf5..d908691 100644 (file)
@@ -8,7 +8,7 @@
 #include "config.h"
 
 #ifndef lint
-static const char sccsid[] = "@(#)db_thread.c  8.12 (Sleepycat) 9/23/97";
+static const char sccsid[] = "@(#)db_thread.c  8.13 (Sleepycat) 10/25/97";
 #endif /* not lint */
 
 #ifndef NO_SYSTEM_INCLUDES
@@ -42,8 +42,7 @@ __db_gethandle(dbp, am_func, dbpp)
        DB *ret_dbp;
        int ret, t_ret;
 
-       if ((ret = __db_mutex_lock((db_mutex_t *)dbp->mutexp, -1,
-           dbp->dbenv == NULL ? NULL : dbp->dbenv->db_yield)) != 0)
+       if ((ret = __db_mutex_lock((db_mutex_t *)dbp->mutexp, -1)) != 0)
                return (ret);
 
        if ((ret_dbp = LIST_FIRST(&dbp->handleq)) != NULL)
@@ -51,7 +50,7 @@ __db_gethandle(dbp, am_func, dbpp)
                LIST_REMOVE(ret_dbp, links);
        else {
                /* Allocate a new handle. */
-               if ((ret_dbp = (DB *)malloc(sizeof(*dbp))) == NULL) {
+               if ((ret_dbp = (DB *)__db_malloc(sizeof(*dbp))) == NULL) {
                        ret = ENOMEM;
                        goto err;
                }
@@ -94,8 +93,7 @@ __db_puthandle(dbp)
        int ret;
 
        master = dbp->master;
-       if ((ret = __db_mutex_lock((db_mutex_t *)master->mutexp, -1,
-           dbp->dbenv == NULL ? NULL : dbp->dbenv->db_yield)) != 0)
+       if ((ret = __db_mutex_lock((db_mutex_t *)master->mutexp, -1)) != 0)
                return (ret);
 
        LIST_INSERT_HEAD(&master->handleq, dbp, links);
index bf5e37e..1affdcd 100644 (file)
@@ -11,7 +11,7 @@
 static const char copyright[] =
 "@(#) Copyright (c) 1997\n\
        Sleepycat Software Inc.  All rights reserved.\n";
-static const char sccsid[] = "@(#)db185.c      8.13 (Sleepycat) 8/24/97";
+static const char sccsid[] = "@(#)db185.c      8.14 (Sleepycat) 10/25/97";
 #endif
 
 #ifndef NO_SYSTEM_INCLUDES
@@ -52,7 +52,7 @@ __dbopen(file, oflags, mode, type, openinfo)
        DB_INFO dbinfo, *dbinfop;
        int s_errno;
 
-       if ((db185p = (DB185 *)calloc(1, sizeof(DB185))) == NULL)
+       if ((db185p = (DB185 *)__db_calloc(1, sizeof(DB185))) == NULL)
                return (NULL);
        dbinfop = NULL;
        memset(&dbinfo, 0, sizeof(dbinfo));
@@ -119,7 +119,7 @@ __dbopen(file, oflags, mode, type, openinfo)
                 */
                if (file != NULL) {
                        if (oflags & O_CREAT && __db_exists(file, NULL) != 0)
-                               (void)close(open(file, oflags, mode));
+                               (void)__os_close(open(file, oflags, mode));
                        dbinfop->re_source = (char *)file;
                        file = NULL;
                }
@@ -131,7 +131,7 @@ __dbopen(file, oflags, mode, type, openinfo)
                         */
 #define        BFMSG   "DB: DB 1.85's recno bfname field is not supported.\n"
                        if (ri->bfname != NULL) {
-                               (void)write(2, BFMSG, sizeof(BFMSG) - 1);
+                               (void)__os_write(2, BFMSG, sizeof(BFMSG) - 1);
                                goto einval;
                        }
 
@@ -183,7 +183,7 @@ __dbopen(file, oflags, mode, type, openinfo)
         */
        if ((__set_errno(db_open(file,
            type, __db_oflags(oflags), mode, NULL, dbinfop, &dbp))) != 0) {
-               free(db185p);
+               __db_free(db185p);
                return (NULL);
        }
 
@@ -192,7 +192,7 @@ __dbopen(file, oflags, mode, type, openinfo)
            != 0) {
                s_errno = errno;
                (void)dbp->close(dbp, 0);
-               free(db185p);
+               __db_free(db185p);
                __set_errno(s_errno);
                return (NULL);
        }
@@ -200,7 +200,7 @@ __dbopen(file, oflags, mode, type, openinfo)
        db185p->internal = dbp;
        return (db185p);
 
-einval:        free(db185p);
+einval:        __db_free(db185p);
        __set_errno(EINVAL);
        return (NULL);
 }
@@ -216,7 +216,7 @@ db185_close(db185p)
 
        __set_errno(dbp->close(dbp, 0));
 
-       free(db185p);
+       __db_free(db185p);
 
        return (errno == 0 ? 0 : -1);
 }
@@ -461,7 +461,7 @@ db185_sync(db185p, flags)
                 * We can't support the R_RECNOSYNC flag.
                 */
 #define        RSMSG   "DB: DB 1.85's R_RECNOSYNC sync flag is not supported.\n"
-               (void)write(2, RSMSG, sizeof(RSMSG) - 1);
+               (void)__os_write(2, RSMSG, sizeof(RSMSG) - 1);
                goto einval;
        default:
                goto einval;
index 56dfddb..1f6c790 100644 (file)
@@ -4,7 +4,7 @@
  * Copyright (c) 1996, 1997
  *     Sleepycat Software.  All rights reserved.
  *
- *     @(#)db_int.h.src        10.30 (Sleepycat) 9/23/97
+ *     @(#)db_int.h.src        10.36 (Sleepycat) 10/31/97
  */
 
 #ifndef _DB_INTERNAL_H_
@@ -12,6 +12,7 @@
 
 #include "db.h"                                /* Standard DB include file. */
 #include "queue.h"
+#include "os_func.h"
 #include "os_ext.h"
 
 /*******************************************************
 #undef SSZA
 #define SSZA(name, field)      ((int)&(((name *)0)->field[0]))
 
+/* Macros to return per-process address, offsets based on shared regions. */
+#define        R_ADDR(base, offset)    ((void *)((u_int8_t *)((base)->addr) + offset))
+#define        R_OFFSET(base, p)       ((u_int8_t *)(p) - (u_int8_t *)(base)->addr)
+
 /* Free and free-string macros that overwrite memory during debugging. */
 #ifdef DEBUG
 #undef FREE
 #define        FREE(p, len) {                                                  \
        memset(p, 0xff, len);                                           \
-       free(p);                                                        \
+       __db_free(p);                                                   \
 }
 #undef FREES
 #define        FREES(p) {                                                      \
 #else
 #undef FREE
 #define        FREE(p, len) {                                                  \
-       free(p);                                                        \
+       __db_free(p);                                                   \
 }
 #undef FREES
 #define        FREES(p) {                                                      \
-       free(p);                                                        \
+       __db_free(p);                                                   \
 }
 #endif
 
 /* Structure used to print flag values. */
 typedef struct __fn {
-       u_int32_t   mask;               /* Flag value. */
+       u_int32_t mask;                 /* Flag value. */
        const char *name;               /* Flag name. */
 } FN;
 
@@ -163,10 +168,8 @@ typedef struct _db_mutex_t {
        off_t   off;                    /* Backing file offset. */
        u_long  pid;                    /* Lock holder: 0 or process pid. */
 #endif
-#ifdef MUTEX_STATISTICS
-       u_long  mutex_set_wait;         /* Blocking mutex: required waiting. */
-       u_long  mutex_set_nowait;       /* Blocking mutex: without waiting. */
-#endif
+       u_int32_t mutex_set_wait;       /* Granted after wait. */
+       u_int32_t mutex_set_nowait;     /* Granted without waiting. */
 } db_mutex_t;
 
 #include "mutex_ext.h"
@@ -177,11 +180,10 @@ typedef struct _db_mutex_t {
 /* Lock/unlock a DB thread. */
 #define        DB_THREAD_LOCK(dbp)                                             \
        (F_ISSET(dbp, DB_AM_THREAD) ?                                   \
-           __db_mutex_lock((db_mutex_t *)(dbp)->mutexp,  -1,           \
-               (dbp)->dbenv == NULL ? NULL : (dbp)->dbenv->db_yield) : 0)
+           __db_mutex_lock((db_mutex_t *)(dbp)->mutexp, -1) : 0)
 #define        DB_THREAD_UNLOCK(dbp)                                           \
        (F_ISSET(dbp, DB_AM_THREAD) ?                                   \
-           __db_mutex_unlock((db_mutex_t *)(dbp)->mutexp,  -1) : 0)
+           __db_mutex_unlock((db_mutex_t *)(dbp)->mutexp, -1) : 0)
 
 /* Btree/recno local statistics structure. */
 struct __db_bt_lstat;  typedef struct __db_bt_lstat DB_BTREE_LSTAT;
@@ -260,7 +262,7 @@ typedef struct __dbpginfo {
 #define        IS_ZERO_LSN(LSN)        ((LSN).file == 0)
 
 /* Test if we need to log a change. */
-#define        DB_LOGGING(dbp) \
+#define        DB_LOGGING(dbp)                                                 \
        (F_ISSET(dbp, DB_AM_LOGGING) && !F_ISSET(dbp, DB_AM_RECOVER))
 
 #ifdef DEBUG
index d986e08..c084953 100644 (file)
@@ -47,7 +47,7 @@
 #include "config.h"
 
 #ifndef lint
-static const char sccsid[] = "@(#)hash.c       10.27 (Sleepycat) 9/15/97";
+static const char sccsid[] = "@(#)hash.c       10.33 (Sleepycat) 11/2/97";
 #endif /* not lint */
 
 #ifndef NO_SYSTEM_INCLUDES
@@ -79,7 +79,7 @@ static int  __ham_cursor __P((DB *, DB_TXN *, DBC **));
 static int  __ham_delete __P((DB *, DB_TXN *, DBT *, int));
 static int  __ham_dup_return __P((HTAB *, HASH_CURSOR *, DBT *, int));
 static int  __ham_get __P((DB *, DB_TXN *, DBT *, DBT *, int));
-static void __ham_init_htab __P((HTAB *));
+static void __ham_init_htab __P((HTAB *, u_int));
 static int  __ham_lookup __P((HTAB *,
                HASH_CURSOR *, const DBT *, u_int32_t, db_lockmode_t));
 static int  __ham_overwrite __P((HTAB *, HASH_CURSOR *, DBT *));
@@ -106,7 +106,7 @@ __ham_open(dbp, dbinfo)
 
        dbenv = dbp->dbenv;
 
-       if ((hashp = (HTAB *)calloc(1, sizeof(HTAB))) == NULL)
+       if ((hashp = (HTAB *)__db_calloc(1, sizeof(HTAB))) == NULL)
                return (ENOMEM);
        hashp->dbp = dbp;
 
@@ -175,10 +175,9 @@ __ham_open(dbp, dbinfo)
                        goto out;
                }
 
-               hashp->hdr->nelem = dbinfo != NULL ? dbinfo->h_nelem : 0;
                hashp->hdr->ffactor =
                    dbinfo != NULL && dbinfo->h_ffactor ? dbinfo->h_ffactor : 0;
-               __ham_init_htab(hashp);
+               __ham_init_htab(hashp, dbinfo != NULL ? dbinfo->h_nelem : 0);
                if (F_ISSET(dbp, DB_AM_DUP))
                        F_SET(hashp->hdr, DB_HASH_DUP);
                if ((ret = __ham_dirty_page(hashp, (PAGE *)hashp->hdr)) != 0)
@@ -190,7 +189,7 @@ __ham_open(dbp, dbinfo)
        TAILQ_INSERT_TAIL(&dbp->curs_queue, curs, links);
 
        /* Allocate memory for our split buffer. */
-       if ((hashp->split_buf = (PAGE *)malloc(dbp->pgsize)) == NULL) {
+       if ((hashp->split_buf = (PAGE *)__db_malloc(dbp->pgsize)) == NULL) {
                ret = ENOMEM;
                goto out;
        }
@@ -265,13 +264,13 @@ __ham_close(dbp)
  * Returns 0 on No Error
  */
 static void
-__ham_init_htab(hashp)
+__ham_init_htab(hashp, nelem)
        HTAB *hashp;
+       u_int nelem;
 {
-       u_int32_t nelem;
        int32_t l2, nbuckets;
 
-       nelem = hashp->hdr->nelem;
+       hashp->hdr->nelem = 0;
        hashp->hdr->pagesize = hashp->dbp->pgsize;
        ZERO_LSN(hashp->hdr->lsn);
        hashp->hdr->magic = DB_HASHMAGIC;
@@ -502,11 +501,11 @@ __ham_c_init(dbp, txnid, dbcp)
        DBC *db_curs;
        HASH_CURSOR *new_curs;
 
-       if ((db_curs = (DBC *)calloc(sizeof(DBC), 1)) == NULL)
+       if ((db_curs = (DBC *)__db_calloc(sizeof(DBC), 1)) == NULL)
                return (ENOMEM);
 
        if ((new_curs =
-           (HASH_CURSOR *)calloc(sizeof(struct cursor_t), 1)) == NULL) {
+           (HASH_CURSOR *)__db_calloc(sizeof(struct cursor_t), 1)) == NULL) {
                FREE(db_curs, sizeof(DBC));
                return (ENOMEM);
        }
@@ -555,7 +554,7 @@ __ham_delete(dbp, txn, key, flags)
        hashp->hash_accesses++;
        if ((ret = __ham_lookup(hashp, hcp, key, 0, DB_LOCK_WRITE)) == 0)
                if (F_ISSET(hcp, H_OK))
-                       ret = __ham_del_pair(hashp, hcp);
+                       ret = __ham_del_pair(hashp, hcp, 1);
                else
                        ret = DB_NOTFOUND;
 
@@ -669,30 +668,41 @@ __ham_c_del(cursor, flags)
        if ((ret = __ham_get_cpage(hashp, hcp, DB_LOCK_WRITE)) != 0)
                goto out;
        if (F_ISSET(hcp, H_ISDUP) && hcp->dpgno != PGNO_INVALID) {
-               ppgno = PREV_PGNO(hcp->dpagep);
-
-               /* Remove item from duplicate page. */
-               chg_pgno = hcp->dpgno;
-               if ((ret = __db_drem(hashp->dbp,
-                   &hcp->dpagep, hcp->dndx, __ham_del_page)) != 0)
-                       goto out;
-
                /*
+                * We are about to remove a duplicate from offpage.
+                *
                 * There are 4 cases.
-                * 1. We removed an item on a page, but nothing else changed.
-                * 2. We removed the last item on a page, but there is a
+                * 1. We will remove an item on a page, but there are more
+                *    items on that page.
+                * 2. We will remove the last item on a page, but there is a
                 *    following page of duplicates.
-                * 3. We removed the last item on a page, this page was the
+                * 3. We will remove the last item on a page, this page was the
                 *    last page in a duplicate set, but there were dups before
                 *    it.
-                * 4. We removed the last item on a page, removing the last
+                * 4. We will remove the last item on a page, removing the last
                 *    duplicate.
                 * In case 1 hcp->dpagep is unchanged.
                 * In case 2 hcp->dpagep comes back pointing to the next dup
                 *     page.
                 * In case 3 hcp->dpagep comes back NULL.
                 * In case 4 hcp->dpagep comes back NULL.
+                *
+                * Case 4 results in deleting the pair off the master page.
+                * The normal code for doing this knows how to delete the
+                * duplicates, so we will handle this case in the normal code.
                 */
+               ppgno = PREV_PGNO(hcp->dpagep);
+               if (ppgno == PGNO_INVALID &&
+                   NEXT_PGNO(hcp->dpagep) == PGNO_INVALID &&
+                   NUM_ENT(hcp->dpagep) == 1)
+                       goto normal;
+
+               /* Remove item from duplicate page. */
+               chg_pgno = hcp->dpgno;
+               if ((ret = __db_drem(hashp->dbp,
+                   &hcp->dpagep, hcp->dndx, __ham_del_page)) != 0)
+                       goto out;
+
                if (hcp->dpagep == NULL) {
                        if (ppgno != PGNO_INVALID) {            /* Case 3 */
                                hcp->dpgno = ppgno;
@@ -702,7 +712,7 @@ __ham_c_del(cursor, flags)
                                hcp->dndx = NUM_ENT(hcp->dpagep);
                                F_SET(hcp, H_DELETED);
                        } else {                                /* Case 4 */
-                               ret = __ham_del_pair(hashp, hcp);
+                               ret = __ham_del_pair(hashp, hcp, 1);
                                hcp->dpgno = PGNO_INVALID;
                                /*
                                 * Delpair updated the cursor queue, so we
@@ -718,14 +728,14 @@ __ham_c_del(cursor, flags)
                                    H_DATAINDEX(hcp->bndx))),
                                    &hcp->dpgno, sizeof(db_pgno_t));
                        F_SET(hcp, H_DELETED);
-               } else                                  /* Case 1 */
+               } else                                          /* Case 1 */
                        F_SET(hcp, H_DELETED);
                if (chg_pgno != PGNO_INVALID)
                        __ham_c_update(hashp, hcp, chg_pgno, 0, 0, 1);
        } else if (F_ISSET(hcp, H_ISDUP)) {                     /* on page */
                if (hcp->dup_off == 0 && DUP_SIZE(hcp->dup_len) ==
                    LEN_HDATA(hcp->pagep, hashp->hdr->pagesize, hcp->bndx))
-                       ret = __ham_del_pair(hashp, hcp);
+                       ret = __ham_del_pair(hashp, hcp, 1);
                else {
                        DBT repldbt;
 
@@ -736,14 +746,14 @@ __ham_c_del(cursor, flags)
                        repldbt.size = 0;
                        ret = __ham_replpair(hashp, hcp, &repldbt, 0);
                        hcp->dup_tlen -= DUP_SIZE(hcp->dup_len);
+                       F_SET(hcp, H_DELETED);
                        __ham_c_update(hashp, hcp, hcp->pgno,
                            DUP_SIZE(hcp->dup_len), 0, 1);
-                       F_SET(hcp, H_DELETED);
                }
 
        } else
                /* Not a duplicate */
-               ret = __ham_del_pair(hashp, hcp);
+normal:                ret = __ham_del_pair(hashp, hcp, 1);
 
 out:   if ((t_ret = __ham_item_done(hashp, hcp, ret == 0)) != 0 && ret == 0)
                t_ret = ret;
@@ -975,8 +985,8 @@ int
 __ham_expand_table(hashp)
        HTAB *hashp;
 {
-       u_int32_t old_bucket, new_bucket;
-       u_int32_t spare_ndx;
+       DB_LSN new_lsn;
+       u_int32_t old_bucket, new_bucket, spare_ndx;
        int ret;
 
        ret = 0;
@@ -984,9 +994,30 @@ __ham_expand_table(hashp)
        if (ret)
                return (ret);
 
-       if (DB_LOGGING(hashp->dbp)) {
-               DB_LSN new_lsn;
+       /*
+        * If the split point is about to increase, make sure that we
+        * have enough extra pages.  The calculation here is weird.
+        * We'd like to do this after we've upped max_bucket, but it's
+        * too late then because we've logged the meta-data split.  What
+        * we'll do between then and now is increment max bucket and then
+        * see what the log of one greater than that is; here we have to
+        * look at the log of max + 2.  VERY NASTY STUFF.
+        */
+       if (__db_log2(hashp->hdr->max_bucket + 2) > hashp->hdr->ovfl_point) {
+               /*
+                * We are about to shift the split point.  Make sure that
+                * if the next doubling is going to be big (more than 8
+                * pages), we have some extra pages around.
+                */
+               if (hashp->hdr->max_bucket + 1 >= 8 && 
+                   hashp->hdr->spares[hashp->hdr->ovfl_point] <
+                   hashp->hdr->spares[hashp->hdr->ovfl_point - 1] + 
+                   hashp->hdr->ovfl_point + 1)
+                       __ham_init_ovflpages(hashp);
+       }
 
+       /* Now we can log the meta-data split. */
+       if (DB_LOGGING(hashp->dbp)) {
                if ((ret = __ham_splitmeta_log(hashp->dbp->dbenv->lg_info,
                    (DB_TXN *)hashp->dbp->txn, &new_lsn, 0,
                    hashp->dbp->log_fileid,
@@ -1003,22 +1034,11 @@ __ham_expand_table(hashp)
        old_bucket = (hashp->hdr->max_bucket & hashp->hdr->low_mask);
 
        /*
-        * If the split point is increasing (hdr.max_bucket's log base 2
-        * increases), max sure that we have enough extra pages, then
-        * copy the current contents of the spare split bucket to the
-        * next bucket.
+        * If the split point is increasing, copy the current contents
+        * of the spare split bucket to the next bucket.
         */
        spare_ndx = __db_log2(hashp->hdr->max_bucket + 1);
        if (spare_ndx > hashp->hdr->ovfl_point) {
-               /*
-                * We are about to shift the split point.  Make sure that
-                * if the next doubling is going to be big (more than 8
-                * pages), we have some extra pages around.
-                */
-               if (hashp->hdr->spares[hashp->hdr->ovfl_point] == 0 &&
-                   new_bucket >= 8)
-                       __ham_init_ovflpages(hashp);
-
                hashp->hdr->spares[spare_ndx] =
                    hashp->hdr->spares[hashp->hdr->ovfl_point];
                hashp->hdr->ovfl_point = spare_ndx;
@@ -1306,7 +1326,7 @@ __ham_init_dbt(dbt, size, bufp, sizep)
        memset(dbt, 0, sizeof(*dbt));
        if (*sizep < size) {
                if ((*bufp = (void *)(*bufp == NULL ?
-                   malloc(size) : realloc(*bufp, size))) == NULL) {
+                   __db_malloc(size) : __db_realloc(*bufp, size))) == NULL) {
                        *sizep = 0;
                        return (ENOMEM);
                }
@@ -1352,9 +1372,20 @@ __ham_c_update(hashp, hcp, chg_pgno, len, add, dup)
        if (!dup && add)
                return;
 
-       page_deleted = chg_pgno != PGNO_INVALID &&
-           ((!dup && chg_pgno != hcp->pgno) ||
-           (dup && chg_pgno != hcp->dpgno));
+       /*
+        * Determine if a page was deleted.    If this is a regular update
+        * (i.e., not dup) then the deleted page's number will be that in
+        * chg_pgno, and the pgno in the cursor will be different.  If this
+        * was an onpage-duplicate, then the same conditions apply.  If this
+        * was an off-page duplicate, then we need to verify if hcp->dpgno
+        * is the same (no delete) or different (delete) than chg_pgno.
+        */
+       if (!dup || hcp->dpgno == PGNO_INVALID)
+               page_deleted =
+                   chg_pgno != PGNO_INVALID && chg_pgno != hcp->pgno;
+       else
+               page_deleted =
+                   chg_pgno != PGNO_INVALID && chg_pgno != hcp->dpgno;
 
        hp = hcp->db_cursor->dbp->master->internal;
        DB_THREAD_LOCK(hp->dbp);
@@ -1432,7 +1463,7 @@ __ham_hdup(orig, new)
        DBC *curs;
        int ret;
 
-       if ((hashp = (HTAB *)malloc(sizeof(HTAB))) == NULL)
+       if ((hashp = (HTAB *)__db_malloc(sizeof(HTAB))) == NULL)
                return (ENOMEM);
 
        new->internal = hashp;
@@ -1441,7 +1472,7 @@ __ham_hdup(orig, new)
        hashp->hlock = 0;
        hashp->hdr = NULL;
        hashp->hash = ((HTAB *)orig->internal)->hash;
-       if ((hashp->split_buf = (PAGE *)malloc(orig->pgsize)) == NULL)
+       if ((hashp->split_buf = (PAGE *)__db_malloc(orig->pgsize)) == NULL)
                return (ENOMEM);
        hashp->local_errno = 0;
        hashp->hash_accesses = 0;
index 04a98d3..8cbcee7 100644 (file)
@@ -43,7 +43,7 @@
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- *     @(#)hash.src    10.1 (Sleepycat) 4/12/97
+ *     @(#)hash.src    10.2 (Sleepycat) 11/2/97
  */
 
 #include "config.h"
@@ -207,5 +207,27 @@ ARG        fileid          u_int32_t       lu
 ARG    start_pgno      db_pgno_t       lu
 ARG    npages          u_int32_t       lu
 ARG    free_pgno       db_pgno_t       lu
+ARG    ovflpoint       u_int32_t       lu
 POINTER        metalsn         DB_LSN *        lu
 END
+
+/*
+ * Used when we empty the first page in a bucket and there are pages
+ * after it.  The page after it gets copied into the bucket page (since
+ * bucket pages have to be in fixed locations).
+ * pgno: the bucket page
+ * pagelsn: the old LSN on the bucket page
+ * next_pgno: the page number of the next page
+ * nnext_pgno: page after next_pgno (may need to change its prev)
+ * nnextlsn: the LSN of nnext_pgno.
+ */
+BEGIN copypage
+ARG    fileid          u_int32_t       lu
+ARG    pgno            db_pgno_t       lu
+POINTER        pagelsn         DB_LSN *        lu
+ARG    next_pgno       db_pgno_t       lu
+POINTER        nextlsn         DB_LSN *        lu
+ARG    nnext_pgno      db_pgno_t       lu
+POINTER        nnextlsn        DB_LSN *        lu
+DBT    page            DBT             s
+END
index 2279de9..4820eb8 100644 (file)
@@ -61,7 +61,7 @@ int __ham_insdel_log(logp, txnid, ret_lsnp, flags,
            + sizeof(*pagelsn)
            + sizeof(u_int32_t) + (key == NULL ? 0 : key->size)
            + sizeof(u_int32_t) + (data == NULL ? 0 : data->size);
-       if ((logrec.data = (void *)malloc(logrec.size)) == NULL)
+       if ((logrec.data = (void *)__db_malloc(logrec.size)) == NULL)
                return (ENOMEM);
 
        bp = logrec.data;
@@ -111,7 +111,7 @@ int __ham_insdel_log(logp, txnid, ret_lsnp, flags,
        ret = log_put(logp, ret_lsnp, (DBT *)&logrec, flags);
        if (txnid != NULL)
                txnid->last_lsn = *ret_lsnp;
-       free(logrec.data);
+       __db_free(logrec.data);
        return (ret);
 }
 
@@ -172,7 +172,7 @@ __ham_insdel_print(notused1, dbtp, lsnp, notused3, notused4)
        }
        printf("\n");
        printf("\n");
-       free(argp);
+       __db_free(argp);
        return (0);
 }
 
@@ -187,7 +187,7 @@ __ham_insdel_read(recbuf, argpp)
        __ham_insdel_args *argp;
        u_int8_t *bp;
 
-       argp = (__ham_insdel_args *)malloc(sizeof(__ham_insdel_args) +
+       argp = (__ham_insdel_args *)__db_malloc(sizeof(__ham_insdel_args) +
            sizeof(DB_TXN));
        if (argp == NULL)
                return (ENOMEM);
@@ -266,7 +266,7 @@ int __ham_newpage_log(logp, txnid, ret_lsnp, flags,
            + sizeof(*pagelsn)
            + sizeof(next_pgno)
            + sizeof(*nextlsn);
-       if ((logrec.data = (void *)malloc(logrec.size)) == NULL)
+       if ((logrec.data = (void *)__db_malloc(logrec.size)) == NULL)
                return (ENOMEM);
 
        bp = logrec.data;
@@ -308,7 +308,7 @@ int __ham_newpage_log(logp, txnid, ret_lsnp, flags,
        ret = log_put(logp, ret_lsnp, (DBT *)&logrec, flags);
        if (txnid != NULL)
                txnid->last_lsn = *ret_lsnp;
-       free(logrec.data);
+       __db_free(logrec.data);
        return (ret);
 }
 
@@ -356,7 +356,7 @@ __ham_newpage_print(notused1, dbtp, lsnp, notused3, notused4)
        printf("\tnextlsn: [%lu][%lu]\n",
            (u_long)argp->nextlsn.file, (u_long)argp->nextlsn.offset);
        printf("\n");
-       free(argp);
+       __db_free(argp);
        return (0);
 }
 
@@ -371,7 +371,7 @@ __ham_newpage_read(recbuf, argpp)
        __ham_newpage_args *argp;
        u_int8_t *bp;
 
-       argp = (__ham_newpage_args *)malloc(sizeof(__ham_newpage_args) +
+       argp = (__ham_newpage_args *)__db_malloc(sizeof(__ham_newpage_args) +
            sizeof(DB_TXN));
        if (argp == NULL)
                return (ENOMEM);
@@ -441,7 +441,7 @@ int __ham_splitmeta_log(logp, txnid, ret_lsnp, flags,
            + sizeof(ovflpoint)
            + sizeof(spares)
            + sizeof(*metalsn);
-       if ((logrec.data = (void *)malloc(logrec.size)) == NULL)
+       if ((logrec.data = (void *)__db_malloc(logrec.size)) == NULL)
                return (ENOMEM);
 
        bp = logrec.data;
@@ -471,7 +471,7 @@ int __ham_splitmeta_log(logp, txnid, ret_lsnp, flags,
        ret = log_put(logp, ret_lsnp, (DBT *)&logrec, flags);
        if (txnid != NULL)
                txnid->last_lsn = *ret_lsnp;
-       free(logrec.data);
+       __db_free(logrec.data);
        return (ret);
 }
 
@@ -514,7 +514,7 @@ __ham_splitmeta_print(notused1, dbtp, lsnp, notused3, notused4)
        printf("\tmetalsn: [%lu][%lu]\n",
            (u_long)argp->metalsn.file, (u_long)argp->metalsn.offset);
        printf("\n");
-       free(argp);
+       __db_free(argp);
        return (0);
 }
 
@@ -529,7 +529,7 @@ __ham_splitmeta_read(recbuf, argpp)
        __ham_splitmeta_args *argp;
        u_int8_t *bp;
 
-       argp = (__ham_splitmeta_args *)malloc(sizeof(__ham_splitmeta_args) +
+       argp = (__ham_splitmeta_args *)__db_malloc(sizeof(__ham_splitmeta_args) +
            sizeof(DB_TXN));
        if (argp == NULL)
                return (ENOMEM);
@@ -594,7 +594,7 @@ int __ham_splitdata_log(logp, txnid, ret_lsnp, flags,
            + sizeof(pgno)
            + sizeof(u_int32_t) + (pageimage == NULL ? 0 : pageimage->size)
            + sizeof(*pagelsn);
-       if ((logrec.data = (void *)malloc(logrec.size)) == NULL)
+       if ((logrec.data = (void *)__db_malloc(logrec.size)) == NULL)
                return (ENOMEM);
 
        bp = logrec.data;
@@ -632,7 +632,7 @@ int __ham_splitdata_log(logp, txnid, ret_lsnp, flags,
        ret = log_put(logp, ret_lsnp, (DBT *)&logrec, flags);
        if (txnid != NULL)
                txnid->last_lsn = *ret_lsnp;
-       free(logrec.data);
+       __db_free(logrec.data);
        return (ret);
 }
 
@@ -683,7 +683,7 @@ __ham_splitdata_print(notused1, dbtp, lsnp, notused3, notused4)
        printf("\tpagelsn: [%lu][%lu]\n",
            (u_long)argp->pagelsn.file, (u_long)argp->pagelsn.offset);
        printf("\n");
-       free(argp);
+       __db_free(argp);
        return (0);
 }
 
@@ -698,7 +698,7 @@ __ham_splitdata_read(recbuf, argpp)
        __ham_splitdata_args *argp;
        u_int8_t *bp;
 
-       argp = (__ham_splitdata_args *)malloc(sizeof(__ham_splitdata_args) +
+       argp = (__ham_splitdata_args *)__db_malloc(sizeof(__ham_splitdata_args) +
            sizeof(DB_TXN));
        if (argp == NULL)
                return (ENOMEM);
@@ -772,7 +772,7 @@ int __ham_replace_log(logp, txnid, ret_lsnp, flags,
            + sizeof(u_int32_t) + (olditem == NULL ? 0 : olditem->size)
            + sizeof(u_int32_t) + (newitem == NULL ? 0 : newitem->size)
            + sizeof(makedup);
-       if ((logrec.data = (void *)malloc(logrec.size)) == NULL)
+       if ((logrec.data = (void *)__db_malloc(logrec.size)) == NULL)
                return (ENOMEM);
 
        bp = logrec.data;
@@ -824,7 +824,7 @@ int __ham_replace_log(logp, txnid, ret_lsnp, flags,
        ret = log_put(logp, ret_lsnp, (DBT *)&logrec, flags);
        if (txnid != NULL)
                txnid->last_lsn = *ret_lsnp;
-       free(logrec.data);
+       __db_free(logrec.data);
        return (ret);
 }
 
@@ -886,7 +886,7 @@ __ham_replace_print(notused1, dbtp, lsnp, notused3, notused4)
        printf("\n");
        printf("\tmakedup: %lu\n", (u_long)argp->makedup);
        printf("\n");
-       free(argp);
+       __db_free(argp);
        return (0);
 }
 
@@ -901,7 +901,7 @@ __ham_replace_read(recbuf, argpp)
        __ham_replace_args *argp;
        u_int8_t *bp;
 
-       argp = (__ham_replace_args *)malloc(sizeof(__ham_replace_args) +
+       argp = (__ham_replace_args *)__db_malloc(sizeof(__ham_replace_args) +
            sizeof(DB_TXN));
        if (argp == NULL)
                return (ENOMEM);
@@ -985,7 +985,7 @@ int __ham_newpgno_log(logp, txnid, ret_lsnp, flags,
            + sizeof(new_type)
            + sizeof(*pagelsn)
            + sizeof(*metalsn);
-       if ((logrec.data = (void *)malloc(logrec.size)) == NULL)
+       if ((logrec.data = (void *)__db_malloc(logrec.size)) == NULL)
                return (ENOMEM);
 
        bp = logrec.data;
@@ -1026,7 +1026,7 @@ int __ham_newpgno_log(logp, txnid, ret_lsnp, flags,
        ret = log_put(logp, ret_lsnp, (DBT *)&logrec, flags);
        if (txnid != NULL)
                txnid->last_lsn = *ret_lsnp;
-       free(logrec.data);
+       __db_free(logrec.data);
        return (ret);
 }
 
@@ -1074,7 +1074,7 @@ __ham_newpgno_print(notused1, dbtp, lsnp, notused3, notused4)
        printf("\tmetalsn: [%lu][%lu]\n",
            (u_long)argp->metalsn.file, (u_long)argp->metalsn.offset);
        printf("\n");
-       free(argp);
+       __db_free(argp);
        return (0);
 }
 
@@ -1089,7 +1089,7 @@ __ham_newpgno_read(recbuf, argpp)
        __ham_newpgno_args *argp;
        u_int8_t *bp;
 
-       argp = (__ham_newpgno_args *)malloc(sizeof(__ham_newpgno_args) +
+       argp = (__ham_newpgno_args *)__db_malloc(sizeof(__ham_newpgno_args) +
            sizeof(DB_TXN));
        if (argp == NULL)
                return (ENOMEM);
@@ -1127,10 +1127,10 @@ __ham_newpgno_read(recbuf, argpp)
  * PUBLIC: int __ham_ovfl_log
  * PUBLIC:     __P((DB_LOG *, DB_TXN *, DB_LSN *, u_int32_t,
  * PUBLIC:     u_int32_t, db_pgno_t, u_int32_t, db_pgno_t,
- * PUBLIC:     DB_LSN *));
+ * PUBLIC:     u_int32_t, DB_LSN *));
  */
 int __ham_ovfl_log(logp, txnid, ret_lsnp, flags,
-       fileid, start_pgno, npages, free_pgno, metalsn)
+       fileid, start_pgno, npages, free_pgno, ovflpoint, metalsn)
        DB_LOG *logp;
        DB_TXN *txnid;
        DB_LSN *ret_lsnp;
@@ -1139,6 +1139,7 @@ int __ham_ovfl_log(logp, txnid, ret_lsnp, flags,
        db_pgno_t start_pgno;
        u_int32_t npages;
        db_pgno_t free_pgno;
+       u_int32_t ovflpoint;
        DB_LSN * metalsn;
 {
        DBT logrec;
@@ -1160,8 +1161,9 @@ int __ham_ovfl_log(logp, txnid, ret_lsnp, flags,
            + sizeof(start_pgno)
            + sizeof(npages)
            + sizeof(free_pgno)
+           + sizeof(ovflpoint)
            + sizeof(*metalsn);
-       if ((logrec.data = (void *)malloc(logrec.size)) == NULL)
+       if ((logrec.data = (void *)__db_malloc(logrec.size)) == NULL)
                return (ENOMEM);
 
        bp = logrec.data;
@@ -1179,6 +1181,8 @@ int __ham_ovfl_log(logp, txnid, ret_lsnp, flags,
        bp += sizeof(npages);
        memcpy(bp, &free_pgno, sizeof(free_pgno));
        bp += sizeof(free_pgno);
+       memcpy(bp, &ovflpoint, sizeof(ovflpoint));
+       bp += sizeof(ovflpoint);
        if (metalsn != NULL)
                memcpy(bp, metalsn, sizeof(*metalsn));
        else
@@ -1191,7 +1195,7 @@ int __ham_ovfl_log(logp, txnid, ret_lsnp, flags,
        ret = log_put(logp, ret_lsnp, (DBT *)&logrec, flags);
        if (txnid != NULL)
                txnid->last_lsn = *ret_lsnp;
-       free(logrec.data);
+       __db_free(logrec.data);
        return (ret);
 }
 
@@ -1231,10 +1235,11 @@ __ham_ovfl_print(notused1, dbtp, lsnp, notused3, notused4)
        printf("\tstart_pgno: %lu\n", (u_long)argp->start_pgno);
        printf("\tnpages: %lu\n", (u_long)argp->npages);
        printf("\tfree_pgno: %lu\n", (u_long)argp->free_pgno);
+       printf("\tovflpoint: %lu\n", (u_long)argp->ovflpoint);
        printf("\tmetalsn: [%lu][%lu]\n",
            (u_long)argp->metalsn.file, (u_long)argp->metalsn.offset);
        printf("\n");
-       free(argp);
+       __db_free(argp);
        return (0);
 }
 
@@ -1249,7 +1254,7 @@ __ham_ovfl_read(recbuf, argpp)
        __ham_ovfl_args *argp;
        u_int8_t *bp;
 
-       argp = (__ham_ovfl_args *)malloc(sizeof(__ham_ovfl_args) +
+       argp = (__ham_ovfl_args *)__db_malloc(sizeof(__ham_ovfl_args) +
            sizeof(DB_TXN));
        if (argp == NULL)
                return (ENOMEM);
@@ -1269,6 +1274,8 @@ __ham_ovfl_read(recbuf, argpp)
        bp += sizeof(argp->npages);
        memcpy(&argp->free_pgno, bp, sizeof(argp->free_pgno));
        bp += sizeof(argp->free_pgno);
+       memcpy(&argp->ovflpoint, bp, sizeof(argp->ovflpoint));
+       bp += sizeof(argp->ovflpoint);
        memcpy(&argp->metalsn, bp,  sizeof(argp->metalsn));
        bp += sizeof(argp->metalsn);
        *argpp = argp;
@@ -1276,6 +1283,207 @@ __ham_ovfl_read(recbuf, argpp)
 }
 
 /*
+ * PUBLIC: int __ham_copypage_log
+ * PUBLIC:     __P((DB_LOG *, DB_TXN *, DB_LSN *, u_int32_t,
+ * PUBLIC:     u_int32_t, db_pgno_t, DB_LSN *, db_pgno_t,
+ * PUBLIC:     DB_LSN *, db_pgno_t, DB_LSN *, DBT *));
+ */
+int __ham_copypage_log(logp, txnid, ret_lsnp, flags,
+       fileid, pgno, pagelsn, next_pgno, nextlsn, nnext_pgno,
+       nnextlsn, page)
+       DB_LOG *logp;
+       DB_TXN *txnid;
+       DB_LSN *ret_lsnp;
+       u_int32_t flags;
+       u_int32_t fileid;
+       db_pgno_t pgno;
+       DB_LSN * pagelsn;
+       db_pgno_t next_pgno;
+       DB_LSN * nextlsn;
+       db_pgno_t nnext_pgno;
+       DB_LSN * nnextlsn;
+       DBT *page;
+{
+       DBT logrec;
+       DB_LSN *lsnp, null_lsn;
+       u_int32_t zero;
+       u_int32_t rectype, txn_num;
+       int ret;
+       u_int8_t *bp;
+
+       rectype = DB_ham_copypage;
+       txn_num = txnid == NULL ? 0 : txnid->txnid;
+       if (txnid == NULL) {
+               null_lsn.file = 0;
+               null_lsn.offset = 0;
+               lsnp = &null_lsn;
+       } else
+               lsnp = &txnid->last_lsn;
+       logrec.size = sizeof(rectype) + sizeof(txn_num) + sizeof(DB_LSN)
+           + sizeof(fileid)
+           + sizeof(pgno)
+           + sizeof(*pagelsn)
+           + sizeof(next_pgno)
+           + sizeof(*nextlsn)
+           + sizeof(nnext_pgno)
+           + sizeof(*nnextlsn)
+           + sizeof(u_int32_t) + (page == NULL ? 0 : page->size);
+       if ((logrec.data = (void *)__db_malloc(logrec.size)) == NULL)
+               return (ENOMEM);
+
+       bp = logrec.data;
+       memcpy(bp, &rectype, sizeof(rectype));
+       bp += sizeof(rectype);
+       memcpy(bp, &txn_num, sizeof(txn_num));
+       bp += sizeof(txn_num);
+       memcpy(bp, lsnp, sizeof(DB_LSN));
+       bp += sizeof(DB_LSN);
+       memcpy(bp, &fileid, sizeof(fileid));
+       bp += sizeof(fileid);
+       memcpy(bp, &pgno, sizeof(pgno));
+       bp += sizeof(pgno);
+       if (pagelsn != NULL)
+               memcpy(bp, pagelsn, sizeof(*pagelsn));
+       else
+               memset(bp, 0, sizeof(*pagelsn));
+       bp += sizeof(*pagelsn);
+       memcpy(bp, &next_pgno, sizeof(next_pgno));
+       bp += sizeof(next_pgno);
+       if (nextlsn != NULL)
+               memcpy(bp, nextlsn, sizeof(*nextlsn));
+       else
+               memset(bp, 0, sizeof(*nextlsn));
+       bp += sizeof(*nextlsn);
+       memcpy(bp, &nnext_pgno, sizeof(nnext_pgno));
+       bp += sizeof(nnext_pgno);
+       if (nnextlsn != NULL)
+               memcpy(bp, nnextlsn, sizeof(*nnextlsn));
+       else
+               memset(bp, 0, sizeof(*nnextlsn));
+       bp += sizeof(*nnextlsn);
+       if (page == NULL) {
+               zero = 0;
+               memcpy(bp, &zero, sizeof(u_int32_t));
+               bp += sizeof(u_int32_t);
+       } else {
+               memcpy(bp, &page->size, sizeof(page->size));
+               bp += sizeof(page->size);
+               memcpy(bp, page->data, page->size);
+               bp += page->size;
+       }
+#ifdef DEBUG
+       if ((u_int32_t)(bp - (u_int8_t *)logrec.data) != logrec.size)
+               fprintf(stderr, "Error in log record length");
+#endif
+       ret = log_put(logp, ret_lsnp, (DBT *)&logrec, flags);
+       if (txnid != NULL)
+               txnid->last_lsn = *ret_lsnp;
+       __db_free(logrec.data);
+       return (ret);
+}
+
+/*
+ * PUBLIC: int __ham_copypage_print
+ * PUBLIC:    __P((DB_LOG *, DBT *, DB_LSN *, int, void *));
+ */
+
+int
+__ham_copypage_print(notused1, dbtp, lsnp, notused3, notused4)
+       DB_LOG *notused1;
+       DBT *dbtp;
+       DB_LSN *lsnp;
+       int notused3;
+       void *notused4;
+{
+       __ham_copypage_args *argp;
+       u_int32_t i;
+       int c, ret;
+
+       i = 0;
+       c = 0;
+       notused1 = NULL;
+       notused3 = 0;
+       notused4 = NULL;
+
+       if ((ret = __ham_copypage_read(dbtp->data, &argp)) != 0)
+               return (ret);
+       printf("[%lu][%lu]ham_copypage: rec: %lu txnid %lx prevlsn [%lu][%lu]\n",
+           (u_long)lsnp->file,
+           (u_long)lsnp->offset,
+           (u_long)argp->type,
+           (u_long)argp->txnid->txnid,
+           (u_long)argp->prev_lsn.file,
+           (u_long)argp->prev_lsn.offset);
+       printf("\tfileid: %lu\n", (u_long)argp->fileid);
+       printf("\tpgno: %lu\n", (u_long)argp->pgno);
+       printf("\tpagelsn: [%lu][%lu]\n",
+           (u_long)argp->pagelsn.file, (u_long)argp->pagelsn.offset);
+       printf("\tnext_pgno: %lu\n", (u_long)argp->next_pgno);
+       printf("\tnextlsn: [%lu][%lu]\n",
+           (u_long)argp->nextlsn.file, (u_long)argp->nextlsn.offset);
+       printf("\tnnext_pgno: %lu\n", (u_long)argp->nnext_pgno);
+       printf("\tnnextlsn: [%lu][%lu]\n",
+           (u_long)argp->nnextlsn.file, (u_long)argp->nnextlsn.offset);
+       printf("\tpage: ");
+       for (i = 0; i < argp->page.size; i++) {
+               c = ((char *)argp->page.data)[i];
+               if (isprint(c) || c == 0xa)
+                       putchar(c);
+               else
+                       printf("%#x ", c);
+       }
+       printf("\n");
+       printf("\n");
+       __db_free(argp);
+       return (0);
+}
+
+/*
+ * PUBLIC: int __ham_copypage_read __P((void *, __ham_copypage_args **));
+ */
+int
+__ham_copypage_read(recbuf, argpp)
+       void *recbuf;
+       __ham_copypage_args **argpp;
+{
+       __ham_copypage_args *argp;
+       u_int8_t *bp;
+
+       argp = (__ham_copypage_args *)__db_malloc(sizeof(__ham_copypage_args) +
+           sizeof(DB_TXN));
+       if (argp == NULL)
+               return (ENOMEM);
+       argp->txnid = (DB_TXN *)&argp[1];
+       bp = recbuf;
+       memcpy(&argp->type, bp, sizeof(argp->type));
+       bp += sizeof(argp->type);
+       memcpy(&argp->txnid->txnid,  bp, sizeof(argp->txnid->txnid));
+       bp += sizeof(argp->txnid->txnid);
+       memcpy(&argp->prev_lsn, bp, sizeof(DB_LSN));
+       bp += sizeof(DB_LSN);
+       memcpy(&argp->fileid, bp, sizeof(argp->fileid));
+       bp += sizeof(argp->fileid);
+       memcpy(&argp->pgno, bp, sizeof(argp->pgno));
+       bp += sizeof(argp->pgno);
+       memcpy(&argp->pagelsn, bp,  sizeof(argp->pagelsn));
+       bp += sizeof(argp->pagelsn);
+       memcpy(&argp->next_pgno, bp, sizeof(argp->next_pgno));
+       bp += sizeof(argp->next_pgno);
+       memcpy(&argp->nextlsn, bp,  sizeof(argp->nextlsn));
+       bp += sizeof(argp->nextlsn);
+       memcpy(&argp->nnext_pgno, bp, sizeof(argp->nnext_pgno));
+       bp += sizeof(argp->nnext_pgno);
+       memcpy(&argp->nnextlsn, bp,  sizeof(argp->nnextlsn));
+       bp += sizeof(argp->nnextlsn);
+       memcpy(&argp->page.size, bp, sizeof(u_int32_t));
+       bp += sizeof(u_int32_t);
+       argp->page.data = bp;
+       bp += argp->page.size;
+       *argpp = argp;
+       return (0);
+}
+
+/*
  * PUBLIC: int __ham_init_print __P((DB_ENV *));
  */
 int
@@ -1305,6 +1513,9 @@ __ham_init_print(dbenv)
        if ((ret = __db_add_recovery(dbenv,
            __ham_ovfl_print, DB_ham_ovfl)) != 0)
                return (ret);
+       if ((ret = __db_add_recovery(dbenv,
+           __ham_copypage_print, DB_ham_copypage)) != 0)
+               return (ret);
        return (0);
 }
 
@@ -1338,6 +1549,9 @@ __ham_init_recover(dbenv)
        if ((ret = __db_add_recovery(dbenv,
            __ham_ovfl_recover, DB_ham_ovfl)) != 0)
                return (ret);
+       if ((ret = __db_add_recovery(dbenv,
+           __ham_copypage_recover, DB_ham_copypage)) != 0)
+               return (ret);
        return (0);
 }
 
index 71bd1c5..22444e4 100644 (file)
@@ -42,7 +42,7 @@
 #include "config.h"
 
 #ifndef lint
-static const char sccsid[] = "@(#)hash_dup.c   10.7 (Sleepycat) 9/15/97";
+static const char sccsid[] = "@(#)hash_dup.c   10.8 (Sleepycat) 10/14/97";
 #endif /* not lint */
 
 /*
@@ -480,7 +480,7 @@ __ham_check_move(hashp, hcp, add_len)
        __ham_copy_item(hashp, hcp->pagep, H_DATAINDEX(hcp->bndx), next_pagep);
 
        /* Now delete the pair from the current page. */
-       ret = __ham_del_pair(hashp, hcp);
+       ret = __ham_del_pair(hashp, hcp, 0);
 
        (void)__ham_put_page(hashp->dbp, hcp->pagep, 1);
        hcp->pagep = next_pagep;
index 8ba42da..0a12c14 100644 (file)
@@ -47,7 +47,7 @@
 #include "config.h"
 
 #ifndef lint
-static const char sccsid[] = "@(#)hash_page.c  10.24 (Sleepycat) 9/17/97";
+static const char sccsid[] = "@(#)hash_page.c  10.29 (Sleepycat) 11/2/97";
 #endif /* not lint */
 
 /*
@@ -489,19 +489,20 @@ __ham_putitem(p, dbt, type)
 
 
 /*
- * PUBLIC: int __ham_del_pair __P((HTAB *, HASH_CURSOR *));
+ * PUBLIC: int __ham_del_pair __P((HTAB *, HASH_CURSOR *, int));
  * XXX TODO: if the item is an offdup, delete the other pages and
  * then remove the pair. If the offpage page is 0, then you can
  * just remove the pair.
  */
 int
-__ham_del_pair(hashp, cursorp)
+__ham_del_pair(hashp, cursorp, reclaim_page)
        HTAB *hashp;
        HASH_CURSOR *cursorp;
+       int reclaim_page;
 {
        DBT data_dbt, key_dbt;
        DB_ENV *dbenv;
-       DB_LSN new_lsn, *n_lsn;
+       DB_LSN new_lsn, *n_lsn, tmp_lsn;
        PAGE *p;
        db_indx_t ndx;
        db_pgno_t chg_pgno, pgno;
@@ -542,6 +543,15 @@ __ham_del_pair(hashp, cursorp)
                            HOFFDUP_PGNO(P_ENTRY(p, H_DATAINDEX(ndx))),
                            sizeof(db_pgno_t));
                        ret = __db_ddup(hashp->dbp, pgno, __ham_del_page);
+                       F_CLR(cursorp, H_ISDUP);
+                       break;
+               case H_DUPLICATE:
+                       /*
+                        * If we delete a pair that is/was a duplicate, then
+                        * we had better clear the flag so that we update the
+                        * cursor appropriately.
+                        */
+                       F_CLR(cursorp, H_ISDUP);
                        break;
                }
 
@@ -578,13 +588,13 @@ __ham_del_pair(hashp, cursorp)
                --hashp->hdr->nelem;
 
        /*
-        * Check if the page is empty.  There are two cases.  If it's
-        * empty and it's not the first chain in the bucket (i.e., the
-        * bucket page) then we can simply remove it. If it is the first
-        * chain in the bucket, then we need to copy the second page into
-        * it and remove the second page.
+        * If we need to reclaim the page, then check if the page is empty.
+        * There are two cases.  If it's empty and it's not the first page
+        * in the bucket (i.e., the bucket page) then we can simply remove
+        * it. If it is the first chain in the bucket, then we need to copy
+        * the second page into it and remove the second page.
         */
-       if (NUM_ENT(p) == 0 && PREV_PGNO(p) == PGNO_INVALID &&
+       if (reclaim_page && NUM_ENT(p) == 0 && PREV_PGNO(p) == PGNO_INVALID &&
            NEXT_PGNO(p) != PGNO_INVALID) {
                PAGE *n_pagep, *nn_pagep;
                db_pgno_t tmp_pgno;
@@ -592,7 +602,6 @@ __ham_del_pair(hashp, cursorp)
                /*
                 * First page in chain is empty and we know that there
                 * are more pages in the chain.
-                * XXX Need to log this.
                 */
                if ((ret =
                    __ham_get_page(hashp->dbp, NEXT_PGNO(p), &n_pagep)) != 0)
@@ -605,13 +614,35 @@ __ham_del_pair(hashp, cursorp)
                                (void) __ham_put_page(hashp->dbp, n_pagep, 0);
                                return (ret);
                        }
+               }
+
+               if (DB_LOGGING(hashp->dbp)) {
+                       key_dbt.data = n_pagep;
+                       key_dbt.size = hashp->hdr->pagesize;
+                       if ((ret = __ham_copypage_log(dbenv->lg_info,
+                           (DB_TXN *)hashp->dbp->txn, &new_lsn, 0,
+                           hashp->dbp->log_fileid, PGNO(p), &LSN(p),
+                           PGNO(n_pagep), &LSN(n_pagep), NEXT_PGNO(n_pagep),
+                           NEXT_PGNO(n_pagep) == PGNO_INVALID ? NULL :
+                           &LSN(nn_pagep), &key_dbt)) != 0)
+                               return (ret);
+
+                       /* Move lsn onto page. */
+                       LSN(p) = new_lsn;       /* Structure assignment. */
+                       LSN(n_pagep) = new_lsn;
+                       if (NEXT_PGNO(n_pagep) != PGNO_INVALID)
+                               LSN(nn_pagep) = new_lsn;
+               }
+               if (NEXT_PGNO(n_pagep) != PGNO_INVALID) {
                        PREV_PGNO(nn_pagep) = PGNO(p);
                        (void)__ham_put_page(hashp->dbp, nn_pagep, 1);
                }
 
                tmp_pgno = PGNO(p);
+               tmp_lsn = LSN(p);
                memcpy(p, n_pagep, hashp->hdr->pagesize);
                PGNO(p) = tmp_pgno;
+               LSN(p) = tmp_lsn;
                PREV_PGNO(p) = PGNO_INVALID;
 
                /*
@@ -623,7 +654,8 @@ __ham_del_pair(hashp, cursorp)
                if ((ret = __ham_dirty_page(hashp, p)) != 0 ||
                    (ret = __ham_del_page(hashp->dbp, n_pagep)) != 0)
                        return (ret);
-       } else if (NUM_ENT(p) == 0 && PREV_PGNO(p) != PGNO_INVALID) {
+       } else if (reclaim_page &&
+           NUM_ENT(p) == 0 && PREV_PGNO(p) != PGNO_INVALID) {
                PAGE *n_pagep, *p_pagep;
 
                if ((ret =
@@ -690,13 +722,22 @@ __ham_del_pair(hashp, cursorp)
        }
        __ham_c_update(hashp, cursorp, chg_pgno, 0, 0, 0);
 
+       /*
+        * Since we just deleted a pair from the master page, anything
+        * in cursorp->dpgno should be cleared.
+        */
+       cursorp->dpgno = PGNO_INVALID;
+
        F_CLR(cursorp, H_OK);
        return (ret);
 }
+
 /*
+ * __ham_replpair --
+ *     Given the key data indicated by the cursor, replace part/all of it
+ *     according to the fields in the dbt.
+ *
  * PUBLIC: int __ham_replpair __P((HTAB *, HASH_CURSOR *, DBT *, u_int32_t));
- * Given the key data indicated by the cursor, replace part/all of it
- * according to the fields in the dbt.
  */
 int
 __ham_replpair(hashp, hcp, dbt, make_dup)
@@ -768,7 +809,7 @@ __ham_replpair(hashp, hcp, dbt, make_dup)
                        return (ret);
 
                if (dbt->doff == 0 && dbt->dlen == len) {
-                       ret = __ham_del_pair(hashp, hcp);
+                       ret = __ham_del_pair(hashp, hcp, 0);
                        if (ret == 0)
                            ret = __ham_add_el(hashp,
                                hcp, &tmp, dbt, H_KEYDATA);
@@ -784,15 +825,15 @@ __ham_replpair(hashp, hcp, dbt, make_dup)
                                goto err;
 
                        /* Now we can delete the item. */
-                       if ((ret = __ham_del_pair(hashp, hcp)) != 0) {
-                               free(tdata.data);
+                       if ((ret = __ham_del_pair(hashp, hcp, 0)) != 0) {
+                               __db_free(tdata.data);
                                goto err;
                        }
 
                        /* Now shift old data around to make room for new. */
                        if (change > 0) {
-                               tdata.data = (void *)
-                                   realloc(tdata.data, tdata.size + change);
+                               tdata.data = (void *)__db_realloc(tdata.data,
+                                   tdata.size + change);
                                memset((u_int8_t *)tdata.data + tdata.size,
                                    0, change);
                        }
@@ -812,9 +853,9 @@ __ham_replpair(hashp, hcp, dbt, make_dup)
 
                        /* Now add the pair. */
                        ret = __ham_add_el(hashp, hcp, &tmp, &tdata, type);
-                       free(tdata.data);
+                       __db_free(tdata.data);
                }
-err:           free(tmp.data);
+err:           __db_free(tmp.data);
                return (ret);
        }
 
@@ -1025,7 +1066,7 @@ __ham_split_page(hashp, obucket, nbucket)
                }
        }
        if (big_buf != NULL)
-               free(big_buf);
+               __db_free(big_buf);
 
        /*
         * If the original bucket spanned multiple pages, then we've got
@@ -1549,17 +1590,20 @@ __ham_init_ovflpages(hp)
 {
        DB_LSN new_lsn;
        PAGE *p;
-       db_pgno_t last_pgno;
-       u_int32_t i, numpages;
+       db_pgno_t last_pgno, new_pgno;
+       u_int32_t i, curpages, numpages;
 
-       numpages = hp->hdr->ovfl_point + 1;
+       curpages = hp->hdr->spares[hp->hdr->ovfl_point] - 
+           hp->hdr->spares[hp->hdr->ovfl_point - 1];
+       numpages = hp->hdr->ovfl_point + 1 - curpages;
 
        last_pgno = hp->hdr->last_freed;
+       new_pgno = PGNO_OF(hp, hp->hdr->ovfl_point, curpages + 1);
        if (DB_LOGGING(hp->dbp)) {
                (void)__ham_ovfl_log(hp->dbp->dbenv->lg_info,
                    (DB_TXN *)hp->dbp->txn, &new_lsn, 0,
-                   hp->dbp->log_fileid, PGNO_OF(hp, hp->hdr->ovfl_point, 1),
-                   numpages, last_pgno, &hp->hdr->lsn);
+                   hp->dbp->log_fileid, new_pgno,
+                   numpages, last_pgno, hp->hdr->ovfl_point, &hp->hdr->lsn);
                hp->hdr->lsn = new_lsn;
        } else
                ZERO_LSN(new_lsn);
@@ -1567,7 +1611,8 @@ __ham_init_ovflpages(hp)
        hp->hdr->spares[hp->hdr->ovfl_point] += numpages;
        for (i = numpages; i > 0; i--) {
                if (__ham_new_page(hp,
-                   PGNO_OF(hp, hp->hdr->ovfl_point, i), P_INVALID, &p) != 0)
+                   PGNO_OF(hp, hp->hdr->ovfl_point, curpages + i),
+                   P_INVALID, &p) != 0)
                        break;
                LSN(p) = new_lsn;
                NEXT_PGNO(p) = last_pgno;
index 1b30be3..d239e3d 100644 (file)
@@ -47,7 +47,7 @@
 #include "config.h"
 
 #ifndef lint
-static const char sccsid[] = "@(#)hash_rec.c   10.13 (Sleepycat) 9/15/97";
+static const char sccsid[] = "@(#)hash_rec.c   10.14 (Sleepycat) 11/2/97";
 #endif /* not lint */
 
 #ifndef NO_SYSTEM_INCLUDES
@@ -756,7 +756,6 @@ __ham_ovfl_recover(logp, dbtp, lsnp, redo, info)
        hashp = (HTAB *)file_dbp->internal;
        GET_META(file_dbp, hashp);
        getmeta = 1;
-       file_dbp = NULL;
 
        cmp_n = log_compare(lsnp, &hashp->hdr->lsn);
        cmp_p = log_compare(&hashp->hdr->lsn, &argp->metalsn);
@@ -764,12 +763,12 @@ __ham_ovfl_recover(logp, dbtp, lsnp, redo, info)
        if (cmp_p == 0 && redo) {
                /* Redo the allocation. */
                hashp->hdr->last_freed = argp->start_pgno;
-               hashp->hdr->spares[argp->npages  - 1] += argp->npages;
+               hashp->hdr->spares[argp->ovflpoint] += argp->npages;
                hashp->hdr->lsn = *lsnp;
                F_SET(file_dbp, DB_HS_DIRTYMETA);
        } else if (cmp_n == 0 && !redo) {
                hashp->hdr->last_freed = argp->free_pgno;
-               hashp->hdr->spares[argp->npages  - 1] -= argp->npages;
+               hashp->hdr->spares[argp->ovflpoint] -= argp->npages;
                hashp->hdr->lsn = argp->metalsn;
                F_SET(file_dbp, DB_HS_DIRTYMETA);
        }
@@ -808,3 +807,142 @@ out:      if (getmeta)
                RELEASE_META(file_dbp, hashp);
        REC_CLOSE;
 }
+
+/*
+ * __ham_copypage_recover --
+ *     Recovery function for copypage.
+ * 
+ * PUBLIC: int __ham_copypage_recover
+ * PUBLIC:   __P((DB_LOG *, DBT *, DB_LSN *, int, void *));
+ */
+int
+__ham_copypage_recover(logp, dbtp, lsnp, redo, info)
+       DB_LOG *logp;
+       DBT *dbtp;
+       DB_LSN *lsnp;
+       int redo;
+       void *info;
+{
+       __ham_copypage_args *argp;
+       DB *file_dbp, *mdbp;
+       DB_MPOOLFILE *mpf;
+       HTAB *hashp;
+       PAGE *pagep;
+       int cmp_n, cmp_p, getmeta, modified, ret;
+
+       getmeta = 0;
+       hashp = NULL;                           /* XXX: shut the compiler up. */
+       REC_PRINT(__ham_copypage_print);
+       REC_INTRO(__ham_copypage_read);
+
+       hashp = (HTAB *)file_dbp->internal;
+       GET_META(file_dbp, hashp);
+       getmeta = 1;
+       modified = 0;
+
+       /* This is the bucket page. */
+       ret = memp_fget(mpf, &argp->pgno, 0, &pagep);
+       if (ret != 0)
+               if (!redo) {
+                       /*
+                        * We are undoing and the page doesn't exist.  That
+                        * is equivalent to having a pagelsn of 0, so we
+                        * would not have to undo anything.  In this case,
+                        * don't bother creating a page.
+                        */
+                       ret = 0;
+                       goto donext;
+               } else if ((ret = memp_fget(mpf, &argp->pgno,
+                   DB_MPOOL_CREATE, &pagep)) != 0)
+                       goto out;
+
+       cmp_n = log_compare(lsnp, &LSN(pagep));
+       cmp_p = log_compare(&LSN(pagep), &argp->pagelsn);
+
+       if (cmp_p == 0 && redo) {
+               /* Need to redo update described. */
+               memcpy(pagep, argp->page.data, argp->page.size);
+               LSN(pagep) = *lsnp;
+               modified = 1;
+       } else if (cmp_n == 0 && !redo) {
+               /* Need to undo update described. */
+               P_INIT(pagep, hashp->hdr->pagesize, argp->pgno, PGNO_INVALID,
+                   argp->next_pgno, 0, P_HASH);
+               LSN(pagep) = argp->pagelsn;
+               modified = 1;
+       }
+       if ((ret = memp_fput(mpf, pagep, modified ? DB_MPOOL_DIRTY : 0)) != 0)
+               goto out;
+
+       /* Now fix up the "next" page. */
+donext:        ret = memp_fget(mpf, &argp->next_pgno, 0, &pagep);
+       if (ret != 0)
+               if (!redo) {
+                       /*
+                        * We are undoing and the page doesn't exist.  That
+                        * is equivalent to having a pagelsn of 0, so we
+                        * would not have to undo anything.  In this case,
+                        * don't bother creating a page.
+                        */
+                       ret = 0;
+                       goto do_nn;
+               } else if ((ret = memp_fget(mpf, &argp->next_pgno,
+                   DB_MPOOL_CREATE, &pagep)) != 0)
+                       goto out;
+
+       /* There is nothing to do in the REDO case; only UNDO. */
+
+       cmp_n = log_compare(lsnp, &LSN(pagep));
+       if (cmp_n == 0 && !redo) {
+               /* Need to undo update described. */
+               memcpy(pagep, argp->page.data, argp->page.size);
+               modified = 1;
+       }
+       if ((ret = memp_fput(mpf, pagep, modified ? DB_MPOOL_DIRTY : 0)) != 0)
+               goto out;
+
+       /* Now fix up the next's next page. */
+do_nn: if (argp->nnext_pgno == PGNO_INVALID) {
+               *lsnp = argp->prev_lsn;
+               goto out;
+       }
+
+       ret = memp_fget(mpf, &argp->nnext_pgno, 0, &pagep);
+       if (ret != 0)
+               if (!redo) {
+                       /*
+                        * We are undoing and the page doesn't exist.  That
+                        * is equivalent to having a pagelsn of 0, so we
+                        * would not have to undo anything.  In this case,
+                        * don't bother creating a page.
+                        */
+                       ret = 0;
+                       *lsnp = argp->prev_lsn;
+                       goto out;
+               } else if ((ret = memp_fget(mpf, &argp->nnext_pgno,
+                   DB_MPOOL_CREATE, &pagep)) != 0)
+                       goto out;
+
+       cmp_n = log_compare(lsnp, &LSN(pagep));
+       cmp_p = log_compare(&LSN(pagep), &argp->nnextlsn);
+
+       if (cmp_p == 0 && redo) {
+               /* Need to redo update described. */
+               PREV_PGNO(pagep) = argp->pgno;
+               LSN(pagep) = *lsnp;
+               modified = 1;
+       } else if (cmp_n == 0 && !redo) {
+               /* Need to undo update described. */
+               PREV_PGNO(pagep) = argp->next_pgno;
+               LSN(pagep) = argp->nnextlsn;
+               modified = 1;
+       }
+       if ((ret = memp_fput(mpf, pagep, modified ? DB_MPOOL_DIRTY : 0)) != 0)
+               goto out;
+
+       *lsnp = argp->prev_lsn;
+
+out:   if (getmeta)
+               RELEASE_META(file_dbp, hashp);
+       REC_CLOSE;
+}
index b422e1d..041b80f 100644 (file)
@@ -58,6 +58,7 @@ typedef struct _bam_rsplit_args {
        u_int32_t       fileid;
        db_pgno_t       pgno;
        DBT     pgdbt;
+       db_pgno_t       nrec;
        DBT     rootent;
        DB_LSN  rootlsn;
 } __bam_rsplit_args;
@@ -105,4 +106,22 @@ typedef struct _bam_cdel_args {
        u_int32_t       indx;
 } __bam_cdel_args;
 
+
+#define        DB_bam_repl     (DB_bam_BEGIN + 8)
+
+typedef struct _bam_repl_args {
+       u_int32_t type;
+       DB_TXN *txnid;
+       DB_LSN prev_lsn;
+       u_int32_t       fileid;
+       db_pgno_t       pgno;
+       DB_LSN  lsn;
+       u_int32_t       indx;
+       u_int32_t       isdeleted;
+       DBT     orig;
+       DBT     repl;
+       u_int32_t       prefix;
+       u_int32_t       suffix;
+} __bam_repl_args;
+
 #endif
index 9133c58..bbe0d97 100644 (file)
@@ -1,4 +1,4 @@
-/* Do not edit: automatically built by dist/distrib. */
+/* DO NOT EDIT: automatically built by dist/distrib. */
 int __bam_close __P((DB *));
 int __bam_sync __P((DB *, int));
 int __bam_cmp __P((DB *, const DBT *, EPG *));
@@ -35,6 +35,7 @@ int __bam_pget __P((DB *, PAGE **, db_pgno_t *, int));
 int __bam_put __P((DB *, DB_TXN *, DBT *, DBT *, int));
 int __bam_iitem __P((DB *,
    PAGE **, db_indx_t *, DBT *, DBT *, int, int));
+int __bam_ritem __P((DB *, PAGE *, u_int32_t, DBT *));
 int __bam_pg_alloc_recover
   __P((DB_LOG *, DBT *, DB_LSN *, int, void *));
 int __bam_pg_free_recover
@@ -49,6 +50,8 @@ int __bam_cadjust_recover
   __P((DB_LOG *, DBT *, DB_LSN *, int, void *));
 int __bam_cdel_recover
   __P((DB_LOG *, DBT *, DB_LSN *, int, void *));
+int __bam_repl_recover
+  __P((DB_LOG *, DBT *, DB_LSN *, int, void *));
 int __ram_open __P((DB *, DBTYPE, DB_INFO *));
 int __ram_cursor __P((DB *, DB_TXN *, DBC **));
 int __ram_close __P((DB *));
@@ -94,8 +97,8 @@ int __bam_split_print
 int __bam_split_read __P((void *, __bam_split_args **));
 int __bam_rsplit_log
     __P((DB_LOG *, DB_TXN *, DB_LSN *, u_int32_t,
-    u_int32_t, db_pgno_t, DBT *, DBT *,
-    DB_LSN *));
+    u_int32_t, db_pgno_t, DBT *, db_pgno_t,
+    DBT *, DB_LSN *));
 int __bam_rsplit_print
    __P((DB_LOG *, DBT *, DB_LSN *, int, void *));
 int __bam_rsplit_read __P((void *, __bam_rsplit_args **));
@@ -119,5 +122,13 @@ int __bam_cdel_log
 int __bam_cdel_print
    __P((DB_LOG *, DBT *, DB_LSN *, int, void *));
 int __bam_cdel_read __P((void *, __bam_cdel_args **));
+int __bam_repl_log
+    __P((DB_LOG *, DB_TXN *, DB_LSN *, u_int32_t,
+    u_int32_t, db_pgno_t, DB_LSN *, u_int32_t,
+    u_int32_t, DBT *, DBT *, u_int32_t,
+    u_int32_t));
+int __bam_repl_print
+   __P((DB_LOG *, DBT *, DB_LSN *, int, void *));
+int __bam_repl_read __P((void *, __bam_repl_args **));
 int __bam_init_print __P((DB_ENV *));
 int __bam_init_recover __P((DB_ENV *));
index 8ccd2b5..91e4a13 100644 (file)
@@ -1,4 +1,4 @@
-/* Do not edit: automatically built by dist/distrib. */
+/* DO NOT EDIT: automatically built by dist/distrib. */
 #ifdef __STDC__
 void err __P((int eval, const char *, ...));
 #else
index 9840162..b814582 100644 (file)
@@ -1,4 +1,4 @@
-/* Do not edit: automatically built by dist/distrib. */
+/* DO NOT EDIT: automatically built by dist/distrib. */
 int __db_appname __P((DB_ENV *,
    APPNAME, const char *, const char *, int *, char **));
 int __db_apprec __P((DB_ENV *, int));
@@ -24,6 +24,7 @@ int __db_ferr __P((const DB_ENV *, const char *, int));
 u_int32_t __db_log2 __P((u_int32_t));
 int __db_rcreate __P((DB_ENV *, APPNAME,
    const char *, const char *, int, size_t, int *, void *));
+int __db_rinit __P((DB_ENV *, RLAYOUT *, int, size_t, int));
 int __db_ropen __P((DB_ENV *,
    APPNAME, const char *, const char *, int, int *, void *));
 int __db_rclose __P((DB_ENV *, int, void *));
index 63d9603..3cc2bfd 100644 (file)
@@ -4,7 +4,7 @@
  * Copyright (c) 1996, 1997
  *     Sleepycat Software.  All rights reserved.
  *
- *     @(#)db.h.src    10.77 (Sleepycat) 9/24/97
+ *     @(#)db.h.src    10.91 (Sleepycat) 11/3/97
  */
 
 #ifndef _DB_H_
  * XXX
  * Handle function prototypes and the keyword "const".  This steps on name
  * space that DB doesn't control, but all of the other solutions are worse.
+ *
+ * XXX
+ * While Microsoft's compiler is ANSI C compliant, it doesn't have _STDC_
+ * defined by default, you specify a command line flag or #pragma to turn
+ * it on.  Don't do that, however, because some of Microsoft's own header
+ * files won't compile.
  */
 #undef __P
-#if defined(__STDC__) || defined(__cplusplus)
+#if defined(__STDC__) || defined(__cplusplus) || defined(_MSC_VER)
 #define        __P(protos)     protos          /* ANSI C prototypes */
 #else
 #define        const
@@ -67,8 +73,8 @@
 
 #define        DB_VERSION_MAJOR        2
 #define        DB_VERSION_MINOR        3
-#define        DB_VERSION_PATCH        10
-#define        DB_VERSION_STRING       "Sleepycat Software: DB 2.3.10: (9/24/97)"
+#define        DB_VERSION_PATCH        12
+#define        DB_VERSION_STRING       "Sleepycat Software: DB 2.3.12: (11/3/97)"
 
 typedef        u_int32_t       db_pgno_t;      /* Page number type. */
 typedef        u_int16_t       db_indx_t;      /* Page offset type. */
@@ -93,6 +99,7 @@ struct __db_lockregion;       typedef struct __db_lockregion DB_LOCKREGION;
 struct __db_lockreq;   typedef struct __db_lockreq DB_LOCKREQ;
 struct __db_locktab;   typedef struct __db_locktab DB_LOCKTAB;
 struct __db_log;       typedef struct __db_log DB_LOG;
+struct __db_log_stat;  typedef struct __db_log_stat DB_LOG_STAT;
 struct __db_lsn;       typedef struct __db_lsn DB_LSN;
 struct __db_mpool;     typedef struct __db_mpool DB_MPOOL;
 struct __db_mpool_fstat;typedef struct __db_mpool_fstat DB_MPOOL_FSTAT;
@@ -122,6 +129,31 @@ struct __db_dbt {
 };
 
 /*
+ * DB configuration.  There are a set of functions which the application
+ * can replace with its own versions.
+ */
+#define        DB_FUNC_CALLOC   1              /* ANSI C calloc. */
+#define        DB_FUNC_CLOSE    2              /* POSIX 1003.1 close. */
+#define        DB_FUNC_DIRFREE  3              /* DB: free directory list. */
+#define        DB_FUNC_DIRLIST  4              /* DB: create directory list. */
+#define        DB_FUNC_EXISTS   5              /* DB: return if file exists. */
+#define        DB_FUNC_FREE     6              /* ANSI C free. */
+#define        DB_FUNC_FSYNC    7              /* POSIX 1003.1 fsync. */
+#define        DB_FUNC_IOINFO   8              /* DB: return file I/O information. */
+#define        DB_FUNC_MALLOC   9              /* ANSI C malloc. */
+#define        DB_FUNC_MAP     10              /* DB: map file into shared memory. */
+#define        DB_FUNC_OPEN    11              /* POSIX 1003.1 open. */
+#define        DB_FUNC_READ    12              /* POSIX 1003.1 read. */
+#define        DB_FUNC_REALLOC 13              /* ANSI C realloc. */
+#define        DB_FUNC_SEEK    14              /* POSIX 1003.1 lseek. */
+#define        DB_FUNC_SLEEP   15              /* DB: sleep secs/usecs. */
+#define        DB_FUNC_STRDUP  16              /* ANSI C strdup. */
+#define        DB_FUNC_UNLINK  17              /* POSIX 1003.1 unlink. */
+#define        DB_FUNC_UNMAP   18              /* DB: unmap shared memory file. */
+#define        DB_FUNC_WRITE   19              /* POSIX 1003.1 write. */
+#define        DB_FUNC_YIELD   20              /* DB: yield thread to scheduler. */
+
+/*
  * Database configuration and initialization.
  */
  /*
@@ -134,21 +166,20 @@ struct __db_dbt {
 /*
  * Flags understood by db_appinit(3).
  *
- * DB_APP_INIT and DB_MUTEXDEBUG are internal only, and not documented.
+ * DB_MUTEXDEBUG is internal only, and not documented.
  */
 /*                             0x00007    COMMON MASK. */
-#define        DB_APP_INIT             0x00008 /* Appinit called, paths initialized. */
-#define        DB_INIT_LOCK            0x00010 /* Initialize locking. */
-#define        DB_INIT_LOG             0x00020 /* Initialize logging. */
-#define        DB_INIT_MPOOL           0x00040 /* Initialize mpool. */
-#define        DB_INIT_TXN             0x00080 /* Initialize transactions. */
-#define        DB_MPOOL_PRIVATE        0x00100 /* Mpool: private memory pool. */
-#define        DB_MUTEXDEBUG           0x00200 /* Do not get/set mutexes in regions. */
-#define        DB_RECOVER              0x00400 /* Run normal recovery. */
-#define        DB_RECOVER_FATAL        0x00800 /* Run catastrophic recovery. */
-#define        DB_TXN_NOSYNC           0x01000 /* Do not sync log on commit. */
-#define        DB_USE_ENVIRON          0x02000 /* Use the environment. */
-#define        DB_USE_ENVIRON_ROOT     0x04000 /* Use the environment if root. */
+#define        DB_INIT_LOCK            0x00008 /* Initialize locking. */
+#define        DB_INIT_LOG             0x00010 /* Initialize logging. */
+#define        DB_INIT_MPOOL           0x00020 /* Initialize mpool. */
+#define        DB_INIT_TXN             0x00040 /* Initialize transactions. */
+#define        DB_MPOOL_PRIVATE        0x00080 /* Mpool: private memory pool. */
+#define        DB_MUTEXDEBUG           0x00100 /* Do not get/set mutexes in regions. */
+#define        DB_RECOVER              0x00200 /* Run normal recovery. */
+#define        DB_RECOVER_FATAL        0x00400 /* Run catastrophic recovery. */
+#define        DB_TXN_NOSYNC           0x00800 /* Do not sync log on commit. */
+#define        DB_USE_ENVIRON          0x01000 /* Use the environment. */
+#define        DB_USE_ENVIRON_ROOT     0x02000 /* Use the environment if root. */
 
 /* CURRENTLY UNUSED LOCK FLAGS. */
 #define        DB_TXN_LOCK_2PL         0x00000 /* Two-phase locking. */
@@ -209,7 +240,6 @@ struct __db_env {
        int              lk_modes;      /* Number of lock modes in table. */
        unsigned int     lk_max;        /* Maximum number of locks. */
        u_int32_t        lk_detect;     /* Deadlock detect on every conflict. */
-       int (*db_yield) __P((void));    /* Yield function for threads. */
 
        /* Logging. */
        DB_LOG          *lg_info;       /* Return from log_open(). */
@@ -226,6 +256,9 @@ struct __db_env {
        int (*tx_recover)               /* Dispatch function for recovery. */
            __P((DB_LOG *, DBT *, DB_LSN *, int, void *));
 
+#define        DB_ENV_APPINIT          0x01    /* Paths initialized by db_appinit(). */
+#define        DB_ENV_STANDALONE       0x02    /* Test: freestanding environment. */
+#define        DB_ENV_THREAD           0x04    /* DB_ENV is multi-threaded. */
        u_int32_t        flags;         /* Flags. */
 };
 
@@ -301,7 +334,7 @@ struct __db_info {
 #define        DB_CURRENT      0x000010        /* c_get(), c_put(), log_get() */
 #define        DB_FIRST        0x000020        /* c_get(), log_get() */
 #define        DB_FLUSH        0x000040        /* log_put() */
-#define        DB_GET_RECNO    0x000080        /* c_get() */
+#define        DB_GET_RECNO    0x000080        /* get(), c_get() */
 #define        DB_KEYFIRST     0x000100        /* c_put() */
 #define        DB_KEYLAST      0x000200        /* c_put() */
 #define        DB_LAST         0x000400        /* c_get(), log_get() */
@@ -312,7 +345,7 @@ struct __db_info {
 #define        DB_RECORDCOUNT  0x008000        /* stat() */
 #define        DB_SET          0x010000        /* c_get(), log_get() */
 #define        DB_SET_RANGE    0x020000        /* c_get() */
-#define        DB_SET_RECNO    0x040000        /* get(), c_get() */
+#define        DB_SET_RECNO    0x040000        /* c_get() */
 
 /* DB (user visible) error return codes. */
 #define        DB_INCOMPLETE           ( -1)   /* Sync didn't finish. */
@@ -472,6 +505,8 @@ struct __db_bt_stat {
        u_int32_t bt_get;               /* Items retrieved. */
        u_int32_t bt_cache_hit;         /* Hits in fast-insert code. */
        u_int32_t bt_cache_miss;        /* Misses in fast-insert code. */
+       u_int32_t bt_magic;             /* Magic number. */
+       u_int32_t bt_version;           /* Version number. */
 };
 
 #if defined(__cplusplus)
@@ -479,6 +514,7 @@ extern "C" {
 #endif
 int   db_appinit __P((const char *, char * const *, DB_ENV *, int));
 int   db_appexit __P((DB_ENV *));
+int   db_jump_set __P((void *, int));
 int   db_open __P((const char *, DBTYPE, int, int, DB_ENV *, DB_INFO *, DB **));
 char *db_version __P((int *, int *, int *));
 #if defined(__cplusplus)
@@ -576,6 +612,22 @@ struct __db_lsn {
        u_int32_t       offset;         /* File offset. */
 };
 
+/* Log statistics structure. */
+struct __db_log_stat {
+       u_int32_t st_magic;             /* Log file magic number. */
+       u_int32_t st_version;           /* Log file version number. */
+       int st_mode;                    /* Log file mode. */
+       u_int32_t st_lg_max;            /* Maximum log file size. */
+       u_int32_t st_w_bytes;           /* Bytes to log. */
+       u_int32_t st_w_mbytes;          /* Megabytes to log. */
+       u_int32_t st_wc_bytes;          /* Bytes to log since checkpoint. */
+       u_int32_t st_wc_mbytes;         /* Megabytes to log since checkpoint. */
+       u_int32_t st_wcount;            /* Total syncs to the log. */
+       u_int32_t st_scount;            /* Total writes to the log. */
+       u_int32_t st_region_wait;       /* Region lock granted after wait. */
+       u_int32_t st_region_nowait;     /* Region lock granted without wait. */
+};
+
 #if defined(__cplusplus)
 extern "C" {
 #endif
@@ -588,6 +640,7 @@ int  log_get __P((DB_LOG *, DB_LSN *, DBT *, int));
 int     log_open __P((const char *, int, int, DB_ENV *, DB_LOG **));
 int     log_put __P((DB_LOG *, DB_LSN *, const DBT *, int));
 int     log_register __P((DB_LOG *, DB *, const char *, DBTYPE, u_int32_t *));
+int     log_stat __P((DB_LOG *, DB_LOG_STAT **, void *(*)(size_t)));
 int     log_unlink __P((const char *, int, DB_ENV *));
 int     log_unregister __P((DB_LOG *, u_int32_t));
 #if defined(__cplusplus)
@@ -610,30 +663,35 @@ int        log_unregister __P((DB_LOG *, u_int32_t));
 /* Mpool statistics structure. */
 struct __db_mpool_stat {
        size_t st_cachesize;            /* Cache size. */
-       unsigned long st_cache_hit;     /* Pages found in the cache. */
-       unsigned long st_cache_miss;    /* Pages not found in the cache. */
-       unsigned long st_map;           /* Pages from mapped files. */
-       unsigned long st_page_create;   /* Pages created in the cache. */
-       unsigned long st_page_in;       /* Pages read in. */
-       unsigned long st_page_out;      /* Pages written out. */
-       unsigned long st_ro_evict;      /* Read-only pages evicted. */
-       unsigned long st_rw_evict;      /* Read-write pages evicted. */
-       unsigned long st_hash_buckets;  /* Number of hash buckets. */
-       unsigned long st_hash_searches; /* Total hash chain searches. */
-       unsigned long st_hash_longest;  /* Longest hash chain searched. */
-       unsigned long st_hash_examined; /* Total hash entries searched. */
+       u_int32_t st_cache_hit;         /* Pages found in the cache. */
+       u_int32_t st_cache_miss;        /* Pages not found in the cache. */
+       u_int32_t st_map;               /* Pages from mapped files. */
+       u_int32_t st_page_create;       /* Pages created in the cache. */
+       u_int32_t st_page_in;           /* Pages read in. */
+       u_int32_t st_page_out;          /* Pages written out. */
+       u_int32_t st_ro_evict;          /* Clean pages forced from the cache. */
+       u_int32_t st_rw_evict;          /* Dirty pages forced from the cache. */
+       u_int32_t st_hash_buckets;      /* Number of hash buckets. */
+       u_int32_t st_hash_searches;     /* Total hash chain searches. */
+       u_int32_t st_hash_longest;      /* Longest hash chain searched. */
+       u_int32_t st_hash_examined;     /* Total hash entries searched. */
+       u_int32_t st_page_clean;        /* Clean pages. */
+       u_int32_t st_page_dirty;        /* Dirty pages. */
+       u_int32_t st_page_trickle;      /* Pages written by memp_trickle. */
+       u_int32_t st_region_wait;       /* Region lock granted after wait. */
+       u_int32_t st_region_nowait;     /* Region lock granted without wait. */
 };
 
 /* Mpool file statistics structure. */
 struct __db_mpool_fstat {
        char *file_name;                /* File name. */
        size_t st_pagesize;             /* Page size. */
-       unsigned long st_cache_hit;     /* Pages found in the cache. */
-       unsigned long st_cache_miss;    /* Pages not found in the cache. */
-       unsigned long st_map;           /* Pages from mapped files. */
-       unsigned long st_page_create;   /* Pages created in the cache. */
-       unsigned long st_page_in;       /* Pages read in. */
-       unsigned long st_page_out;      /* Pages written out. */
+       u_int32_t st_cache_hit;         /* Pages found in the cache. */
+       u_int32_t st_cache_miss;        /* Pages not found in the cache. */
+       u_int32_t st_map;               /* Pages from mapped files. */
+       u_int32_t st_page_create;       /* Pages created in the cache. */
+       u_int32_t st_page_in;           /* Pages read in. */
+       u_int32_t st_page_out;          /* Pages written out. */
 };
 
 #if defined(__cplusplus)
@@ -654,6 +712,7 @@ int memp_register __P((DB_MPOOL *, int,
 int    memp_stat __P((DB_MPOOL *,
            DB_MPOOL_STAT **, DB_MPOOL_FSTAT ***, void *(*)(size_t)));
 int    memp_sync __P((DB_MPOOL *, DB_LSN *));
+int    memp_trickle __P((DB_MPOOL *, int, int *));
 int    memp_unlink __P((const char *, int, DB_ENV *));
 #if defined(__cplusplus)
 };
index 5814ff8..0ea24be 100644 (file)
@@ -4,7 +4,7 @@
  * Copyright (c) 1996, 1997
  *     Sleepycat Software.  All rights reserved.
  *
- *     @(#)db_am.h     10.6 (Sleepycat) 8/27/97
+ *     @(#)db_am.h     10.7 (Sleepycat) 10/25/97
  */
 #ifndef _DB_AM_H
 #define _DB_AM_H
@@ -49,7 +49,7 @@
 }
 #define        REC_CLOSE {                                                     \
        if (argp != NULL)                                               \
-               free (argp);                                            \
+               __db_free(argp);                                        \
        if (file_dbp != NULL) {                                         \
                F_CLR(file_dbp, DB_AM_RECOVER);                         \
                if (F_ISSET(file_dbp, DB_AM_THREAD))                    \
@@ -67,7 +67,7 @@
 }
 #define        REC_NOOP_CLOSE {                                                \
        if (argp != NULL)                                               \
-               free (argp);                                            \
+               __db_free(argp);                                        \
        return (ret);                                                   \
 }
 
index 7478173..4c7b4da 100644 (file)
@@ -59,6 +59,7 @@ typedef struct _db_ovref_args {
        DB_LSN prev_lsn;
        u_int32_t       fileid;
        db_pgno_t       pgno;
+       int32_t adjust;
        DB_LSN  lsn;
 } __db_ovref_args;
 
index 611d967..01d1231 100644 (file)
@@ -4,12 +4,11 @@
  * Copyright (c) 1997
  *     Sleepycat Software.  All rights reserved.
  *
- *     @(#)db_cxx.h    10.8 (Sleepycat) 9/20/97
+ *     @(#)db_cxx.h    10.12 (Sleepycat) 10/25/97
  */
 
 #ifndef _DB_CXX_H_
 #define _DB_CXX_H_
-
 //
 // C++ assumptions:
 //
@@ -264,7 +263,7 @@ public:
     // Normally these would be called register and unregister to
     // parallel the C interface, but "register" is a reserved word.
     //
-    int db_register(Db *dbp, const char *name, u_int32_t *fidp);
+    int db_register(Db *dbp, const char *name, DBTYPE type, u_int32_t *fidp);
     int db_unregister(u_int32_t fid);
 
     // Create or remove new log files
@@ -353,6 +352,7 @@ public:
     int stat(DB_MPOOL_STAT **gsp, DB_MPOOL_FSTAT ***fsp,
              void *(*db_malloc)(size_t));
     int sync(DbLsn *lsn);
+    int trickle(int pct, int *nwrotep);
 
     // Create or remove new mpool files
     //
@@ -598,6 +598,11 @@ public:
     //
     int appinit(const char *homeDir, char *const *db_config, int flags);
 
+    // Called automatically when DbEnv is destroyed, or can be
+    // called at any time to shut down Db.
+    //
+    int appexit();
+
     ////////////////////////////////////////////////////////////////
     // simple get/set access methods
     //
@@ -675,11 +680,6 @@ public:
     u_int32_t get_lk_detect() const;
     void set_lk_detect(u_int32_t);
 
-    // Yield function for threads.
-    typedef int (*db_yield_fcn) (void);
-    db_yield_fcn get_yield() const;
-    void set_yield(db_yield_fcn);
-
 
     ////////////////////////////////////////////////////////////////
     // Logging.
@@ -783,7 +783,7 @@ class _exported Db
 public:
     int close(int flags);
     int cursor(DbTxn *txnid, Dbc **cursorp);
-    int del(Dbt *key, DbTxn *txnid);
+    int del(DbTxn *txnid, Dbt *key, int flags);
     int fd(int *fdp);
     int get(DbTxn *txnid, Dbt *key, Dbt *data, int flags);
     int put(DbTxn *txnid, Dbt *key, Dbt *data, int flags);
@@ -884,5 +884,4 @@ private:
     Dbc(const Dbc &);
     Dbc &operator = (const Dbc &);
 };
-
 #endif /* !_DB_CXX_H_ */
index b18b10f..f9b3b3a 100644 (file)
@@ -1,4 +1,4 @@
-/* Do not edit: automatically built by dist/distrib. */
+/* DO NOT EDIT: automatically built by dist/distrib. */
 int __db_pgerr __P((DB *, db_pgno_t));
 int __db_pgfmt __P((DB *, db_pgno_t));
 int __db_addrem_log
@@ -25,7 +25,7 @@ int __db_big_print
 int __db_big_read __P((void *, __db_big_args **));
 int __db_ovref_log
     __P((DB_LOG *, DB_TXN *, DB_LSN *, u_int32_t,
-    u_int32_t, db_pgno_t, DB_LSN *));
+    u_int32_t, db_pgno_t, int32_t, DB_LSN *));
 int __db_ovref_print
    __P((DB_LOG *, DBT *, DB_LSN *, int, void *));
 int __db_ovref_read __P((void *, __db_ovref_args **));
@@ -79,7 +79,7 @@ int __db_goff __P((DB *, DBT *,
     u_int32_t, db_pgno_t, void **, u_int32_t *));
 int __db_poff __P((DB *, const DBT *, db_pgno_t *,
     int (*)(DB *, u_int32_t, PAGE **)));
-int __db_ioff __P((DB *, db_pgno_t));
+int __db_ovref __P((DB *, db_pgno_t, int));
 int __db_doff __P((DB *, db_pgno_t, int (*)(DB *, PAGE *)));
 int __db_moff __P((DB *, const DBT *, db_pgno_t));
 void __db_loadme __P((void));
index ebadb35..abd93a6 100644 (file)
@@ -4,7 +4,7 @@
  * Copyright (c) 1996, 1997
  *     Sleepycat Software.  All rights reserved.
  *
- *     @(#)db_int.h.src        10.30 (Sleepycat) 9/23/97
+ *     @(#)db_int.h.src        10.36 (Sleepycat) 10/31/97
  */
 
 #ifndef _DB_INTERNAL_H_
@@ -12,6 +12,7 @@
 
 #include "db.h"                                /* Standard DB include file. */
 #include "queue.h"
+#include "os_func.h"
 #include "os_ext.h"
 
 /*******************************************************
 #undef SSZA
 #define SSZA(name, field)      ((int)&(((name *)0)->field[0]))
 
+/* Macros to return per-process address, offsets based on shared regions. */
+#define        R_ADDR(base, offset)    ((void *)((u_int8_t *)((base)->addr) + offset))
+#define        R_OFFSET(base, p)       ((u_int8_t *)(p) - (u_int8_t *)(base)->addr)
+
 /* Free and free-string macros that overwrite memory during debugging. */
 #ifdef DEBUG
 #undef FREE
 #define        FREE(p, len) {                                                  \
        memset(p, 0xff, len);                                           \
-       free(p);                                                        \
+       __db_free(p);                                                   \
 }
 #undef FREES
 #define        FREES(p) {                                                      \
 #else
 #undef FREE
 #define        FREE(p, len) {                                                  \
-       free(p);                                                        \
+       __db_free(p);                                                   \
 }
 #undef FREES
 #define        FREES(p) {                                                      \
-       free(p);                                                        \
+       __db_free(p);                                                   \
 }
 #endif
 
 /* Structure used to print flag values. */
 typedef struct __fn {
        u_int32_t mask;                 /* Flag value. */
-       char     *name;                 /* Flag name. */
+       const char *name;               /* Flag name. */
 } FN;
 
 /* Set, clear and test flags. */
@@ -163,10 +168,8 @@ typedef struct _db_mutex_t {
        off_t   off;                    /* Backing file offset. */
        u_long  pid;                    /* Lock holder: 0 or process pid. */
 #endif
-#ifdef MUTEX_STATISTICS
-       u_long  mutex_set_wait;         /* Blocking mutex: required waiting. */
-       u_long  mutex_set_nowait;       /* Blocking mutex: without waiting. */
-#endif
+       u_int32_t mutex_set_wait;       /* Granted after wait. */
+       u_int32_t mutex_set_nowait;     /* Granted without waiting. */
 } db_mutex_t;
 
 #include "mutex_ext.h"
@@ -177,11 +180,10 @@ typedef struct _db_mutex_t {
 /* Lock/unlock a DB thread. */
 #define        DB_THREAD_LOCK(dbp)                                             \
        (F_ISSET(dbp, DB_AM_THREAD) ?                                   \
-           __db_mutex_lock((db_mutex_t *)(dbp)->mutexp,  -1,           \
-               (dbp)->dbenv == NULL ? NULL : (dbp)->dbenv->db_yield) : 0)
+           __db_mutex_lock((db_mutex_t *)(dbp)->mutexp, -1) : 0)
 #define        DB_THREAD_UNLOCK(dbp)                                           \
        (F_ISSET(dbp, DB_AM_THREAD) ?                                   \
-           __db_mutex_unlock((db_mutex_t *)(dbp)->mutexp,  -1) : 0)
+           __db_mutex_unlock((db_mutex_t *)(dbp)->mutexp, -1) : 0)
 
 /* Btree/recno local statistics structure. */
 struct __db_bt_lstat;  typedef struct __db_bt_lstat DB_BTREE_LSTAT;
@@ -260,7 +262,7 @@ typedef struct __dbpginfo {
 #define        IS_ZERO_LSN(LSN)        ((LSN).file == 0)
 
 /* Test if we need to log a change. */
-#define        DB_LOGGING(dbp) \
+#define        DB_LOGGING(dbp)                                                 \
        (F_ISSET(dbp, DB_AM_LOGGING) && !F_ISSET(dbp, DB_AM_RECOVER))
 
 #ifdef DEBUG
index cb8ea35..ae6d384 100644 (file)
@@ -43,7 +43,7 @@
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- *     @(#)hash.h      10.6 (Sleepycat) 8/18/97
+ *     @(#)hash.h      10.7 (Sleepycat) 11/1/97
  */
 
 /* Cursor structure definitions. */
@@ -179,8 +179,8 @@ typedef struct htab {        &