Update.
authorUlrich Drepper <drepper@redhat.com>
Tue, 9 Jun 1998 15:16:55 +0000 (15:16 +0000)
committerUlrich Drepper <drepper@redhat.com>
Tue, 9 Jun 1998 15:16:55 +0000 (15:16 +0000)
1998-06-09  Ulrich Drepper  <drepper@cygnus.com>

* sysdeps/unix/sysv/linux/netinet/ip.h (struct ip_options): Define
__data member only for gcc.  Reported by ak@muc.de.

* misc/mntent.h: Undo last patch.
* sysdeps/unix/sysv/linux/fstatvfs.c (fstatvfs): Undo last patch.
* misc/tst/mntent.c: Adjust code for this change.

* io/fts.c: Updated from a slightly more recent BSD version.
* io/fts.h: Likewise.

* libc.map: Add __libc_stack_end.

* db2/Makefile (routines): Add lock_region.
* db2/config.h: Update from db-2.4.14.
* db2/db.h: Likewise.
* db2/db_185.h: Likewise.
* db2/db_int.h: Likewise.
* db2/bt_close.c: Likewise.
* db2/bt_compare.c: Likewise.
* db2/bt_conv.c: Likewise.
* db2/bt_cursor.c: Likewise.
* db2/bt_delete.c: Likewise.
* db2/bt_open.c: Likewise.
* db2/bt_page.c: Likewise.
* db2/bt_put.c: Likewise.
* db2/bt_rec.c: Likewise.
* db2/bt_recno.c: Likewise.
* db2/bt_rsearch.c: Likewise.
* db2/bt_search.c: Likewise.
* db2/bt_split.c: Likewise.
* db2/bt_stat.c: Likewise.
* db2/btree.src: Likewise.
* db2/btree_auto.c: Likewise.
* db2/getlong.c: Likewise.
* db2/db_appinit.c: Likewise.
* db2/db_apprec.c: Likewise.
* db2/db_byteorder.c: Likewise.
* db2/db_err.c: Likewise.
* db2/db_log2.c: Likewise.
* db2/db_region.c: Likewise.
* db2/db_salloc.c: Likewise.
* db2/db_shash.c: Likewise.
* db2/db.c: Likewise.
* db2/db.src: Likewise.
* db2/db_auto.c: Likewise.
* db2/db_conv.c: Likewise.
* db2/db_dispatch.c: Likewise.
* db2/db_dup.c: Likewise.
* db2/db_overflow.c: Likewise.
* db2/db_pr.c: Likewise.
* db2/db_rec.c: Likewise.
* db2/db_ret.c: Likewise.
* db2/db_thread.c: Likewise.
* db2/db185.c: Likewise.
* db2/db185_int.h: Likewise.
* db2/dbm.c: Likewise.
* db2/hash.c: Likewise.
* db2/hash.src: Likewise.
* db2/hash_auto.c: Likewise.
* db2/hash_conv.c: Likewise.
* db2/hash_debug.c: Likewise.
* db2/hash_dup.c: Likewise.
* db2/hash_func.c: Likewise.
* db2/hash_page.c: Likewise.
* db2/hash_rec.c: Likewise.
* db2/hash_stat.c: Likewise.
* db2/btree.h: Likewise.
* db2/btree_ext.h: Likewise.
* db2/clib_ext.h: Likewise.
* db2/common_ext.h: Likewise.
* db2/cxx_int.h: Likewise.
* db2/db.h.src: Likewise.
* db2/db_185.h.src: Likewise.
* db2/db_am.h: Likewise.
* db2/db_auto.h: Likewise.
* db2/db_cxx.h: Likewise.
* db2/db_dispatch.h: Likewise.
* db2/db_ext.h: Likewise.
* db2/db_int.h.src: Likewise.
* db2/db_page.h: Likewise.
* db2/db_shash.h: Likewise.
* db2/db_swap.h: Likewise.
* db2/hash.h: Likewise.
* db2/hash_ext.h: Likewise.
* db2/lock.h: Likewise.
* db2/lock_ext.h: Likewise.
* db2/log.h: Likewise.
* db2/log_ext.h: Likewise.
* db2/mp.h: Likewise.
* db2/mp_ext.h: Likewise.
* db2/mutex_ext.h: Likewise.
* db2/os_ext.h: Likewise.
* db2/os_func.h: Likewise.
* db2/queue.h: Likewise.
* db2/shqueue.h: Likewise.
* db2/txn.h: Likewise.
* db2/lock.c: Likewise.
* db2/lock_conflict.c: Likewise.
* db2/lock_deadlock.c: Likewise.
* db2/lock_region.c: Likewise.
* db2/lock_util.c: Likewise.
* db2/log.c: Likewise.
* db2/log.src: Likewise.
* db2/log_archive.c: Likewise.
* db2/log_auto.c: Likewise.
* db2/log_compare.c: Likewise.
* db2/log_findckp.c: Likewise.
* db2/log_get.c: Likewise.
* db2/log_put.c: Likewise.
* db2/log_rec.c: Likewise.
* db2/log_register.c: Likewise.
* db2/mp_bh.c: Likewise.
* db2/mp_fget.c: Likewise.
* db2/mp_fopen.c: Likewise.
* db2/mp_fput.c: Likewise.
* db2/mp_fset.c: Likewise.
* db2/mp_open.c: Likewise.
* db2/mp_pr.c: Likewise.
* db2/mp_region.c: Likewise.
* db2/mp_sync.c: Likewise.
* db2/68020.gcc: Likewise.
* db2/mutex.c: Likewise.
* db2/parisc.gcc: Likewise.
* db2/parisc.hp: Likewise.
* db2/sco.cc: Likewise.
* db2/os_abs.c: Likewise.
* db2/os_alloc.c: Likewise.
* db2/os_config.c: Likewise.
* db2/os_dir.c: Likewise.
* db2/os_fid.c: Likewise.
* db2/os_fsync.c: Likewise.
* db2/os_map.c: Likewise.
* db2/os_oflags.c: Likewise.
* db2/os_open.c: Likewise.
* db2/os_rpath.c: Likewise.
* db2/os_rw.c: Likewise.
* db2/os_seek.c: Likewise.
* db2/os_sleep.c: Likewise.
* db2/os_spin.c: Likewise.
* db2/os_stat.c: Likewise.
* db2/os_unlink.c: Likewise.
* db2/db_archive.c: Likewise.
* db2/db_checkpoint.c: Likewise.
* db2/db_deadlock.c: Likewise.
* db2/db_dump.c: Likewise.
* db2/db_dump185.c: Likewise.
* db2/db_load.c: Likewise.
* db2/db_printlog.c: Likewise.
* db2/db_recover.c: Likewise.
* db2/db_stat.c: Likewise.
* db2/txn.c: Likewise.
* db2/txn.src: Likewise.
* db2/txn_auto.c: Likewise.
* db2/txn_rec.c: Likewise.

* elf/rtld.c: Move definition of __libc_stack_end to ...
* sysdeps/generic/dl-sysdep.h: ...here.

* sysdeps/unix/sysv/linux/fstatvfs.c: Handle nodiratime option.
* sysdeps/unix/sysv/linux/bits/statvfs.h: Define ST_NODIRATIME.
* sysdeps/unix/sysv/linux/sys/mount.h: Define MS_NODIRATIME.

1998-06-08 21:44  Ulrich Drepper  <drepper@cygnus.com>

* sysdeps/unix/sysv/linux/fstatvfs.c: Handle constant option string
from mntent correctly.

1998-06-06  Andreas Jaeger  <aj@arthur.rhein-neckar.de>

* sunrpc/Makefile (generated): Correct typo.

1998-06-04  Philip Blundell  <philb@gnu.org>

* elf/elf.h (EM_ARM, et al.): New definitions.
* sysdeps/arm/dl-machine.h: Update for new draft ARM ELF ABI.

161 files changed:
ChangeLog
db2/Makefile
db2/btree/bt_close.c
db2/btree/bt_compare.c
db2/btree/bt_conv.c
db2/btree/bt_cursor.c
db2/btree/bt_delete.c
db2/btree/bt_open.c
db2/btree/bt_page.c
db2/btree/bt_put.c
db2/btree/bt_rec.c
db2/btree/bt_recno.c
db2/btree/bt_rsearch.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/clib/getlong.c
db2/common/db_appinit.c
db2/common/db_apprec.c
db2/common/db_byteorder.c
db2/common/db_err.c
db2/common/db_log2.c
db2/common/db_region.c
db2/common/db_salloc.c
db2/common/db_shash.c
db2/config.h
db2/db.h
db2/db/db.c
db2/db/db.src
db2/db/db_auto.c
db2/db/db_conv.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/db185/db185_int.h
db2/db_185.h
db2/db_int.h
db2/dbm/dbm.c
db2/hash/hash.c
db2/hash/hash.src
db2/hash/hash_auto.c
db2/hash/hash_conv.c
db2/hash/hash_debug.c
db2/hash/hash_dup.c
db2/hash/hash_func.c
db2/hash/hash_page.c
db2/hash/hash_rec.c
db2/hash/hash_stat.c
db2/include/btree.h
db2/include/btree_ext.h
db2/include/clib_ext.h
db2/include/common_ext.h
db2/include/cxx_int.h
db2/include/db.h.src
db2/include/db_185.h.src
db2/include/db_am.h
db2/include/db_auto.h
db2/include/db_cxx.h
db2/include/db_dispatch.h
db2/include/db_ext.h
db2/include/db_int.h.src
db2/include/db_page.h
db2/include/db_shash.h
db2/include/db_swap.h
db2/include/hash.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
db2/include/queue.h
db2/include/shqueue.h
db2/include/txn.h
db2/lock/lock.c
db2/lock/lock_conflict.c
db2/lock/lock_deadlock.c
db2/lock/lock_region.c [new file with mode: 0644]
db2/lock/lock_util.c
db2/log/log.c
db2/log/log.src
db2/log/log_archive.c
db2/log/log_auto.c
db2/log/log_compare.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/68020.gcc
db2/mutex/mutex.c
db2/mutex/parisc.gcc
db2/mutex/parisc.hp
db2/mutex/sco.cc [new file with mode: 0644]
db2/os/os_abs.c
db2/os/os_alloc.c
db2/os/os_config.c
db2/os/os_dir.c
db2/os/os_fid.c
db2/os/os_fsync.c
db2/os/os_map.c
db2/os/os_oflags.c
db2/os/os_open.c
db2/os/os_rpath.c
db2/os/os_rw.c
db2/os/os_seek.c
db2/os/os_sleep.c
db2/os/os_spin.c
db2/os/os_stat.c
db2/os/os_unlink.c
db2/progs/db_archive/db_archive.c
db2/progs/db_checkpoint/db_checkpoint.c
db2/progs/db_deadlock/db_deadlock.c
db2/progs/db_dump/db_dump.c
db2/progs/db_dump185/db_dump185.c
db2/progs/db_load/db_load.c
db2/progs/db_printlog/db_printlog.c
db2/progs/db_recover/db_recover.c
db2/progs/db_stat/db_stat.c
db2/txn/txn.c
db2/txn/txn.src
db2/txn/txn_auto.c
db2/txn/txn_rec.c
elf/elf.h
elf/rtld.c
io/fts.c
io/fts.h
libc.map
linuxthreads/internals.h
linuxthreads/manager.c
linuxthreads/mutex.c
linuxthreads/pthread.c
misc/mntent.h
misc/tst-mntent.c
sunrpc/Makefile
sysdeps/arm/dl-machine.h
sysdeps/generic/dl-sysdep.c
sysdeps/unix/sysv/linux/bits/statvfs.h
sysdeps/unix/sysv/linux/fstatvfs.c
sysdeps/unix/sysv/linux/netinet/ip.h
sysdeps/unix/sysv/linux/sys/mount.h

index 549cdf7..28e90b8 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,181 @@
+1998-06-09  Ulrich Drepper  <drepper@cygnus.com>
+
+       * sysdeps/unix/sysv/linux/netinet/ip.h (struct ip_options): Define
+       __data member only for gcc.  Reported by ak@muc.de.
+
+       * misc/mntent.h: Undo last patch.
+       * sysdeps/unix/sysv/linux/fstatvfs.c (fstatvfs): Undo last patch.
+       * misc/tst/mntent.c: Adjust code for this change.
+
+       * io/fts.c: Updated from a slightly more recent BSD version.
+       * io/fts.h: Likewise.
+
+       * libc.map: Add __libc_stack_end.
+
+       * db2/Makefile (routines): Add lock_region.
+       * db2/config.h: Update from db-2.4.14.
+       * db2/db.h: Likewise.
+       * db2/db_185.h: Likewise.
+       * db2/db_int.h: Likewise.
+       * db2/bt_close.c: Likewise.
+       * db2/bt_compare.c: Likewise.
+       * db2/bt_conv.c: Likewise.
+       * db2/bt_cursor.c: Likewise.
+       * db2/bt_delete.c: Likewise.
+       * db2/bt_open.c: Likewise.
+       * db2/bt_page.c: Likewise.
+       * db2/bt_put.c: Likewise.
+       * db2/bt_rec.c: Likewise.
+       * db2/bt_recno.c: Likewise.
+       * db2/bt_rsearch.c: Likewise.
+       * db2/bt_search.c: Likewise.
+       * db2/bt_split.c: Likewise.
+       * db2/bt_stat.c: Likewise.
+       * db2/btree.src: Likewise.
+       * db2/btree_auto.c: Likewise.
+       * db2/getlong.c: Likewise.
+       * db2/db_appinit.c: Likewise.
+       * db2/db_apprec.c: Likewise.
+       * db2/db_byteorder.c: Likewise.
+       * db2/db_err.c: Likewise.
+       * db2/db_log2.c: Likewise.
+       * db2/db_region.c: Likewise.
+       * db2/db_salloc.c: Likewise.
+       * db2/db_shash.c: Likewise.
+       * db2/db.c: Likewise.
+       * db2/db.src: Likewise.
+       * db2/db_auto.c: Likewise.
+       * db2/db_conv.c: Likewise.
+       * db2/db_dispatch.c: Likewise.
+       * db2/db_dup.c: Likewise.
+       * db2/db_overflow.c: Likewise.
+       * db2/db_pr.c: Likewise.
+       * db2/db_rec.c: Likewise.
+       * db2/db_ret.c: Likewise.
+       * db2/db_thread.c: Likewise.
+       * db2/db185.c: Likewise.
+       * db2/db185_int.h: Likewise.
+       * db2/dbm.c: Likewise.
+       * db2/hash.c: Likewise.
+       * db2/hash.src: Likewise.
+       * db2/hash_auto.c: Likewise.
+       * db2/hash_conv.c: Likewise.
+       * db2/hash_debug.c: Likewise.
+       * db2/hash_dup.c: Likewise.
+       * db2/hash_func.c: Likewise.
+       * db2/hash_page.c: Likewise.
+       * db2/hash_rec.c: Likewise.
+       * db2/hash_stat.c: Likewise.
+       * db2/btree.h: Likewise.
+       * db2/btree_ext.h: Likewise.
+       * db2/clib_ext.h: Likewise.
+       * db2/common_ext.h: Likewise.
+       * db2/cxx_int.h: Likewise.
+       * db2/db.h.src: Likewise.
+       * db2/db_185.h.src: Likewise.
+       * db2/db_am.h: Likewise.
+       * db2/db_auto.h: Likewise.
+       * db2/db_cxx.h: Likewise.
+       * db2/db_dispatch.h: Likewise.
+       * db2/db_ext.h: Likewise.
+       * db2/db_int.h.src: Likewise.
+       * db2/db_page.h: Likewise.
+       * db2/db_shash.h: Likewise.
+       * db2/db_swap.h: Likewise.
+       * db2/hash.h: Likewise.
+       * db2/hash_ext.h: Likewise.
+       * db2/lock.h: Likewise.
+       * db2/lock_ext.h: Likewise.
+       * db2/log.h: Likewise.
+       * db2/log_ext.h: Likewise.
+       * db2/mp.h: Likewise.
+       * db2/mp_ext.h: Likewise.
+       * db2/mutex_ext.h: Likewise.
+       * db2/os_ext.h: Likewise.
+       * db2/os_func.h: Likewise.
+       * db2/queue.h: Likewise.
+       * db2/shqueue.h: Likewise.
+       * db2/txn.h: Likewise.
+       * db2/lock.c: Likewise.
+       * db2/lock_conflict.c: Likewise.
+       * db2/lock_deadlock.c: Likewise.
+       * db2/lock_region.c: Likewise.
+       * db2/lock_util.c: Likewise.
+       * db2/log.c: Likewise.
+       * db2/log.src: Likewise.
+       * db2/log_archive.c: Likewise.
+       * db2/log_auto.c: Likewise.
+       * db2/log_compare.c: Likewise.
+       * db2/log_findckp.c: Likewise.
+       * db2/log_get.c: Likewise.
+       * db2/log_put.c: Likewise.
+       * db2/log_rec.c: Likewise.
+       * db2/log_register.c: Likewise.
+       * db2/mp_bh.c: Likewise.
+       * db2/mp_fget.c: Likewise.
+       * db2/mp_fopen.c: Likewise.
+       * db2/mp_fput.c: Likewise.
+       * db2/mp_fset.c: Likewise.
+       * db2/mp_open.c: Likewise.
+       * db2/mp_pr.c: Likewise.
+       * db2/mp_region.c: Likewise.
+       * db2/mp_sync.c: Likewise.
+       * db2/68020.gcc: Likewise.
+       * db2/mutex.c: Likewise.
+       * db2/parisc.gcc: Likewise.
+       * db2/parisc.hp: Likewise.
+       * db2/sco.cc: Likewise.
+       * db2/os_abs.c: Likewise.
+       * db2/os_alloc.c: Likewise.
+       * db2/os_config.c: Likewise.
+       * db2/os_dir.c: Likewise.
+       * db2/os_fid.c: Likewise.
+       * db2/os_fsync.c: Likewise.
+       * db2/os_map.c: Likewise.
+       * db2/os_oflags.c: Likewise.
+       * db2/os_open.c: Likewise.
+       * db2/os_rpath.c: Likewise.
+       * db2/os_rw.c: Likewise.
+       * db2/os_seek.c: Likewise.
+       * db2/os_sleep.c: Likewise.
+       * db2/os_spin.c: Likewise.
+       * db2/os_stat.c: Likewise.
+       * db2/os_unlink.c: Likewise.
+       * db2/db_archive.c: Likewise.
+       * db2/db_checkpoint.c: Likewise.
+       * db2/db_deadlock.c: Likewise.
+       * db2/db_dump.c: Likewise.
+       * db2/db_dump185.c: Likewise.
+       * db2/db_load.c: Likewise.
+       * db2/db_printlog.c: Likewise.
+       * db2/db_recover.c: Likewise.
+       * db2/db_stat.c: Likewise.
+       * db2/txn.c: Likewise.
+       * db2/txn.src: Likewise.
+       * db2/txn_auto.c: Likewise.
+       * db2/txn_rec.c: Likewise.
+
+       * elf/rtld.c: Move definition of __libc_stack_end to ...
+       * sysdeps/generic/dl-sysdep.h: ...here.
+
+       * sysdeps/unix/sysv/linux/fstatvfs.c: Handle nodiratime option.
+       * sysdeps/unix/sysv/linux/bits/statvfs.h: Define ST_NODIRATIME.
+       * sysdeps/unix/sysv/linux/sys/mount.h: Define MS_NODIRATIME.
+
+1998-06-08 21:44  Ulrich Drepper  <drepper@cygnus.com>
+
+       * sysdeps/unix/sysv/linux/fstatvfs.c: Handle constant option string
+       from mntent correctly.
+
+1998-06-06  Andreas Jaeger  <aj@arthur.rhein-neckar.de>
+
+       * sunrpc/Makefile (generated): Correct typo.
+
+1998-06-04  Philip Blundell  <philb@gnu.org>
+
+       * elf/elf.h (EM_ARM, et al.): New definitions.
+       * sysdeps/arm/dl-machine.h: Update for new draft ARM ELF ABI.
+
 1998-06-08 21:33  Ulrich Drepper  <drepper@cygnus.com>
 
        * localedata/SUPPORTED: Add sk_SK.
index 35c67da..cc530a8 100644 (file)
@@ -65,7 +65,7 @@ libdb-routines := bt_close bt_compare bt_conv bt_cursor bt_delete \
        os_spin 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 \
-       lock_conflict lock_deadlock lock_util log log_archive \
+       lock_conflict lock_deadlock lock_region lock_util log log_archive \
        log_auto log_compare log_findckp log_get log_put log_rec \
        log_register mp_bh mp_fget mp_fopen mp_fput mp_fset \
        mp_open mp_pr mp_region mp_sync mutex txn txn_auto \
index ecccc9f..9df5c71 100644 (file)
@@ -1,7 +1,7 @@
 /*-
  * See the file LICENSE for redistribution information.
  *
- * Copyright (c) 1996, 1997
+ * Copyright (c) 1996, 1997, 1998
  *     Sleepycat Software.  All rights reserved.
  */
 /*
 #include "config.h"
 
 #ifndef lint
-static const char sccsid[] = "@(#)bt_close.c   10.25 (Sleepycat) 1/6/98";
+static const char sccsid[] = "@(#)bt_close.c   10.32 (Sleepycat) 5/6/98";
 #endif /* not lint */
 
 #ifndef NO_SYSTEM_INCLUDES
 #include <sys/types.h>
-#include <sys/mman.h>
 
-#include <errno.h>
-#include <stdio.h>
-#include <stdlib.h>
 #include <string.h>
-#include <unistd.h>
 #endif
 
 #include "db_int.h"
@@ -104,12 +99,12 @@ __bam_close(dbp)
  * __bam_sync --
  *     Sync the btree to disk.
  *
- * PUBLIC: int __bam_sync __P((DB *, int));
+ * PUBLIC: int __bam_sync __P((DB *, u_int32_t));
  */
 int
 __bam_sync(argdbp, flags)
        DB *argdbp;
-       int flags;
+       u_int32_t flags;
 {
        DB *dbp;
        int ret;
@@ -146,7 +141,7 @@ __bam_upstat(dbp)
        BTMETA *meta;
        DB_LOCK metalock;
        db_pgno_t pgno;
-       int flags, ret;
+       u_int32_t flags;
 
        /*
         * We use a no-op log call to log the update of the statistics onto the
@@ -166,8 +161,8 @@ __bam_upstat(dbp)
        if (__bam_pget(dbp, (PAGE **)&meta, &pgno, 0) == 0) {
                /* Log the change. */
                if (DB_LOGGING(dbp) &&
-                   (ret = __db_noop_log(dbp->dbenv->lg_info, dbp->txn,
-                   &LSN(meta), 0)) == 0)
+                   __db_noop_log(dbp->dbenv->lg_info, dbp->txn, &LSN(meta), 0,
+                   dbp->log_fileid, PGNO_METADATA, &LSN(meta)) != 0)
                        goto err;
 
                /* Update the statistics. */
index a68b1fa..5c6d1e3 100644 (file)
@@ -1,7 +1,7 @@
 /*-
  * See the file LICENSE for redistribution information.
  *
- * Copyright (c) 1996, 1997
+ * Copyright (c) 1996, 1997, 1998
  *     Sleepycat Software.  All rights reserved.
  */
 /*
 #include "config.h"
 
 #ifndef lint
-static const char sccsid[] = "@(#)bt_compare.c 10.4 (Sleepycat) 9/3/97";
+static const char sccsid[] = "@(#)bt_compare.c 10.9 (Sleepycat) 5/6/98";
 #endif /* not lint */
 
 #ifndef NO_SYSTEM_INCLUDES
 #include <sys/types.h>
 
-#include <stdio.h>
-#include <stdlib.h>
 #include <string.h>
 #endif
 
@@ -106,7 +104,6 @@ __bam_cmp(dbp, k1, e)
                if (B_TYPE(bk->type) == B_OVERFLOW)
                        bo = (BOVERFLOW *)bk;
                else {
-                       memset(&k2, 0, sizeof(k2));
                        k2.data = bk->data;
                        k2.size = bk->len;
                }
@@ -115,7 +112,6 @@ __bam_cmp(dbp, k1, e)
                if (B_TYPE(bi->type) == B_OVERFLOW)
                        bo = (BOVERFLOW *)(bi->data);
                else {
-                       memset(&k2, 0, sizeof(k2));
                        k2.data = bi->data;
                        k2.size = bi->len;
                }
@@ -139,10 +135,21 @@ __bam_cmp(dbp, k1, e)
                 * Otherwise, we need a contiguous record so we can hand it
                 * to the user's routine.
                 */
+               memset(&k2, 0, sizeof(k2));
                if (__db_goff(dbp, &k2, bo->tlen,
-                   bo->pgno, &t->bt_rdata.data, &t->bt_rdata.ulen) != 0)
-                       abort();
+                   bo->pgno, &t->bt_rdata.data, &t->bt_rdata.ulen) != 0) {
+                       (void)__db_panic(dbp);
+                       return (0);
+               }
        }
+
+       /*
+        * XXX
+        * Note, we have not cleared the k2 DBT in this path.  This should
+        * be okay, because the user's comparison routine had better not be
+        * looking at any fields other than the data/size.  We don't clear
+        * it because we go through this path a lot and it's expensive.
+        */
        return ((*t->bt_compare)(k1, &k2));
 }
 
index c89493c..3da4507 100644 (file)
@@ -1,14 +1,14 @@
 /*-
  * See the file LICENSE for redistribution information.
  *
- * Copyright (c) 1996, 1997
+ * Copyright (c) 1996, 1997, 1998
  *     Sleepycat Software.  All rights reserved.
  */
 
 #include "config.h"
 
 #ifndef lint
-static const char sccsid[] = "@(#)bt_conv.c    10.5 (Sleepycat) 9/15/97";
+static const char sccsid[] = "@(#)bt_conv.c    10.6 (Sleepycat) 4/10/98";
 #endif /* not lint */
 
 #ifndef NO_SYSTEM_INCLUDES
index f526c96..cfa3887 100644 (file)
@@ -1,22 +1,20 @@
 /*-
  * See the file LICENSE for redistribution information.
  *
- * Copyright (c) 1996, 1997
+ * Copyright (c) 1996, 1997, 1998
  *     Sleepycat Software.  All rights reserved.
  */
 
 #include "config.h"
 
 #ifndef lint
-static const char sccsid[] = "@(#)bt_cursor.c  10.41 (Sleepycat) 1/8/98";
+static const char sccsid[] = "@(#)bt_cursor.c  10.53 (Sleepycat) 5/25/98";
 #endif /* not lint */
 
 #ifndef NO_SYSTEM_INCLUDES
 #include <sys/types.h>
 
 #include <errno.h>
-#include <stdio.h>
-#include <stdlib.h>
 #include <string.h>
 #endif
 
@@ -25,24 +23,30 @@ static const char sccsid[] = "@(#)bt_cursor.c       10.41 (Sleepycat) 1/8/98";
 #include "btree.h"
 
 static int __bam_c_close __P((DBC *));
-static int __bam_c_del __P((DBC *, int));
+static int __bam_c_del __P((DBC *, u_int32_t));
 static int __bam_c_first __P((DB *, CURSOR *));
-static int __bam_c_get __P((DBC *, DBT *, DBT *, int));
+static int __bam_c_get __P((DBC *, DBT *, DBT *, u_int32_t));
+static int __bam_c_getstack __P((DB *, CURSOR *));
 static int __bam_c_last __P((DB *, CURSOR *));
 static int __bam_c_next __P((DB *, CURSOR *, int));
 static int __bam_c_physdel __P((DB *, CURSOR *, PAGE *));
 static int __bam_c_prev __P((DB *, CURSOR *));
-static int __bam_c_put __P((DBC *, DBT *, DBT *, int));
-static int __bam_c_rget __P((DB *, CURSOR *, DBT *, int));
-static int __bam_c_search __P((DB *, CURSOR *, const DBT *, u_int, int, int *));
+static int __bam_c_put __P((DBC *, DBT *, DBT *, u_int32_t));
+static int __bam_c_rget __P((DB *, CURSOR *, DBT *, u_int32_t));
+static int __bam_c_search
+              __P((DB *, CURSOR *, const DBT *, u_int32_t, int, int *));
 
 /* Discard the current page/lock held by a cursor. */
 #undef DISCARD
 #define        DISCARD(dbp, cp) {                                              \
-       (void)memp_fput(dbp->mpf, (cp)->page, 0);                       \
-       (cp)->page = NULL;                                              \
-       (void)__BT_TLPUT((dbp), (cp)->lock);                            \
-       (cp)->lock = LOCK_INVALID;                                      \
+       if ((cp)->page != NULL) {                                       \
+               (void)memp_fput(dbp->mpf, (cp)->page, 0);               \
+               (cp)->page = NULL;                                      \
+       }                                                               \
+       if ((cp)->lock != LOCK_INVALID) {                               \
+               (void)__BT_TLPUT((dbp), (cp)->lock);                    \
+               (cp)->lock = LOCK_INVALID;                              \
+       }                                                               \
 }
 
 /*
@@ -85,9 +89,9 @@ __bam_cursor(dbp, txn, dbcp)
         * All cursors are queued from the master DB structure.  Add the
         * cursor to that queue.
         */
-       DB_THREAD_LOCK(dbp);
+       CURSOR_SETUP(dbp);
        TAILQ_INSERT_HEAD(&dbp->curs_queue, dbc, links);
-       DB_THREAD_UNLOCK(dbp);
+       CURSOR_TEARDOWN(dbp);
 
        *dbcp = dbc;
        return (0);
@@ -128,13 +132,6 @@ __bam_c_iclose(dbp, dbc)
        CURSOR *cp;
        int ret;
 
-       /*
-        * All cursors are queued from the master DB structure.  For
-        * now, discard the DB handle which triggered this call, and
-        * replace it with the cursor's reference.
-        */
-       dbp = dbc->dbp;
-
        /* If a cursor key was deleted, perform the actual deletion.  */
        cp = dbc->internal;
        ret = F_ISSET(cp, C_DELETED) ? __bam_c_physdel(dbp, cp, NULL) : 0;
@@ -144,9 +141,9 @@ __bam_c_iclose(dbp, dbc)
                (void)__BT_TLPUT(dbp, cp->lock);
 
        /* Remove the cursor from the queue. */
-       DB_THREAD_LOCK(dbp);
+       CURSOR_SETUP(dbp);
        TAILQ_REMOVE(&dbp->curs_queue, dbc, links);
-       DB_THREAD_UNLOCK(dbp);
+       CURSOR_TEARDOWN(dbp);
 
        /* Discard the structures. */
        FREE(dbc->internal, sizeof(CURSOR));
@@ -162,8 +159,9 @@ __bam_c_iclose(dbp, dbc)
 static int
 __bam_c_del(dbc, flags)
        DBC *dbc;
-       int flags;
+       u_int32_t flags;
 {
+       BTREE *t;
        CURSOR *cp;
        DB *dbp;
        DB_LOCK lock;
@@ -175,6 +173,7 @@ __bam_c_del(dbc, flags)
        DEBUG_LWRITE(dbc->dbp, dbc->txn, "bam_c_del", NULL, NULL, flags);
 
        cp = dbc->internal;
+       h = NULL;
 
        /* Check for invalid flags. */
        if ((ret = __db_cdelchk(dbc->dbp, flags,
@@ -186,6 +185,7 @@ __bam_c_del(dbc, flags)
                return (DB_KEYEMPTY);
 
        GETHANDLE(dbc->dbp, dbc->txn, &dbp, ret);
+       t = dbp->internal;
 
        /*
         * We don't physically delete the record until the cursor moves,
@@ -235,8 +235,21 @@ __bam_c_del(dbc, flags)
        (void)__bam_ca_delete(dbp, pgno, indx, NULL, 0);
 
        ret = memp_fput(dbp->mpf, h, DB_MPOOL_DIRTY);
+       h = NULL;
+
+       /*
+        * If it's a btree with record numbers, we have to adjust the
+        * counts.
+        */
+       if (F_ISSET(dbp, DB_BT_RECNUM) &&
+           (ret = __bam_c_getstack(dbp, cp)) == 0) {
+               ret = __bam_adjust(dbp, t, -1);
+               (void)__bam_stkrel(dbp);
+       }
 
-err:   PUTHANDLE(dbp);
+err:   if (h != NULL)
+               (void)memp_fput(dbp->mpf, h, 0);
+       PUTHANDLE(dbp);
        return (ret);
 }
 
@@ -244,14 +257,14 @@ err:      PUTHANDLE(dbp);
  * __bam_get --
  *     Retrieve a key/data pair from the tree.
  *
- * PUBLIC: int __bam_get __P((DB *, DB_TXN *, DBT *, DBT *, int));
+ * PUBLIC: int __bam_get __P((DB *, DB_TXN *, DBT *, DBT *, u_int32_t));
  */
 int
 __bam_get(argdbp, txn, key, data, flags)
        DB *argdbp;
        DB_TXN *txn;
        DBT *key, *data;
-       int flags;
+       u_int32_t flags;
 {
        DBC dbc;
        CURSOR cp;
@@ -289,7 +302,7 @@ static int
 __bam_c_get(dbc, key, data, flags)
        DBC *dbc;
        DBT *key, *data;
-       int flags;
+       u_int32_t flags;
 {
        BTREE *t;
        CURSOR *cp, copy;
@@ -448,7 +461,7 @@ __bam_c_rget(dbp, cp, data, flags)
        DB *dbp;
        CURSOR *cp;
        DBT *data;
-       int flags;
+       u_int32_t flags;
 {
        BTREE *t;
        DBT dbt;
@@ -491,7 +504,7 @@ static int
 __bam_c_put(dbc, key, data, flags)
        DBC *dbc;
        DBT *key, *data;
-       int flags;
+       u_int32_t flags;
 {
        BTREE *t;
        CURSOR *cp, copy;
@@ -499,7 +512,8 @@ __bam_c_put(dbc, key, data, flags)
        DBT dbt;
        db_indx_t indx;
        db_pgno_t pgno;
-       int exact, needkey, ret;
+       u_int32_t iiflags;
+       int exact, needkey, ret, stack;
        void *arg;
 
        DEBUG_LWRITE(dbc->dbp, dbc->txn, "bam_c_put",
@@ -524,29 +538,34 @@ __bam_c_put(dbc, key, data, flags)
         * To split, we need a valid key for the page.  Since it's a cursor,
         * we have to build one.
         */
+       stack = 0;
        if (0) {
-split:         if (needkey) {
+split:         /* Acquire a copy of a key from the page. */
+               if (needkey) {
                        memset(&dbt, 0, sizeof(DBT));
-                       ret = __db_ret(dbp, cp->page, indx,
-                           &dbt, &t->bt_rkey.data, &t->bt_rkey.ulen);
-
-                       DISCARD(dbp, cp);
-
-                       if (ret)
+                       if ((ret = __db_ret(dbp, cp->page, indx,
+                           &dbt, &t->bt_rkey.data, &t->bt_rkey.ulen)) != 0)
                                goto err;
                        arg = &dbt;
-               } else {
-                       (void)__bam_stkrel(dbp);
+               } else
                        arg = key;
-               }
+
+               /* Discard any pinned pages. */
+               if (stack) {
+                       (void)__bam_stkrel(dbp);
+                       stack = 0;
+               } else
+                       DISCARD(dbp, cp);
+
                if ((ret = __bam_split(dbp, arg)) != 0)
                        goto err;
        }
 
-       /* If there's no key supplied, use the cursor. */
-       if (flags == DB_KEYFIRST || flags == DB_KEYLAST)
-               needkey = 0;
-       else {
+       ret = 0;
+       switch (flags) {
+       case DB_AFTER:
+       case DB_BEFORE:
+       case DB_CURRENT:
                needkey = 1;
                if (cp->dpgno == PGNO_INVALID) {
                        pgno = cp->pgno;
@@ -555,41 +574,53 @@ split:            if (needkey) {
                        pgno = cp->dpgno;
                        indx = cp->dindx;
                }
-               /* Acquire the current page. */
-               if ((ret = __bam_lget(dbp,
-                   0, cp->pgno, DB_LOCK_WRITE, &cp->lock)) != 0)
-                       goto err;
-               if ((ret = __bam_pget(dbp, &cp->page, &pgno, 0)) != 0)
-                       goto err;
-       }
+               /*
+                * XXX
+                * This test is right -- we don't currently support duplicates
+                * in the presence of record numbers, so we don't worry about
+                * them if DB_BT_RECNUM is set.
+                */
+               if (F_ISSET(dbp, DB_BT_RECNUM) &&
+                   (flags != DB_CURRENT || F_ISSET(cp, C_DELETED))) {
+                       /* Acquire a complete stack. */
+                       if ((ret = __bam_c_getstack(dbp, cp)) != 0)
+                               goto err;
+                       cp->page = t->bt_csp->page;
 
-       ret = 0;
-       switch (flags) {
-       case DB_AFTER:
-       case DB_BEFORE:
-       case DB_CURRENT:
+                       stack = 1;
+                       iiflags = BI_DOINCR;
+               } else {
+                       /* Acquire the current page. */
+                       if ((ret = __bam_lget(dbp,
+                           0, cp->pgno, DB_LOCK_WRITE, &cp->lock)) == 0)
+                               ret = __bam_pget(dbp, &cp->page, &pgno, 0);
+                       if (ret != 0)
+                               goto err;
+
+                       iiflags = 0;
+               }
                if ((ret = __bam_iitem(dbp, &cp->page,
-                   &indx, key, data, flags, 0)) == DB_NEEDSPLIT)
+                   &indx, key, data, flags, iiflags)) == DB_NEEDSPLIT)
                        goto split;
                break;
        case DB_KEYFIRST:
-               exact = 0;
+               exact = needkey = 0;
                if ((ret =
                    __bam_c_search(dbp, cp, key, S_KEYFIRST, 0, &exact)) != 0)
                        goto err;
+               stack = 1;
 
                indx = cp->dpgno == PGNO_INVALID ? cp->indx : cp->dindx;
                if ((ret = __bam_iitem(dbp, &cp->page, &indx, key,
                    data, DB_BEFORE, exact ? 0 : BI_NEWKEY)) == DB_NEEDSPLIT)
                        goto split;
-               if (ret)
-                       goto err;
                break;
        case DB_KEYLAST:
-               exact = 0;
+               exact = needkey = 0;
                if ((ret =
                    __bam_c_search(dbp, cp, key, S_KEYLAST, 0, &exact)) != 0)
                        goto err;
+               stack = 1;
 
                indx = cp->dpgno == PGNO_INVALID ? cp->indx : cp->dindx;
                if ((ret = __bam_iitem(dbp, &cp->page, &indx, key,
@@ -623,13 +654,27 @@ split:            if (needkey) {
        if (copy.lock != LOCK_INVALID)
                (void)__BT_TLPUT(dbp, copy.lock);
 
-       /* Discard the pinned page. */
-       ret = memp_fput(dbp->mpf, cp->page, 0);
+       /*
+        * Discard any pages pinned in the tree and their locks, except for
+        * the leaf page, for which we only discard the pin, not the lock.
+        *
+        * Note, the leaf page participated in the stack we acquired, and so
+        * we have to adjust the stack as necessary.  If there was only a
+        * single page on the stack, we don't have to free further stack pages.
+        */
+
+       if (stack && BT_STK_POP(t) != NULL)
+               (void)__bam_stkrel(dbp);
+
+       if ((ret = memp_fput(dbp->mpf, cp->page, 0)) != 0)
+               goto err;
+
        if (0) {
-err:           if (cp->page != NULL)
-                       (void)memp_fput(dbp->mpf, cp->page, 0);
-               if (cp->lock != LOCK_INVALID)
-                       (void)__BT_TLPUT(dbp, cp->lock);
+err:           /* Discard any pinned pages. */
+               if (stack)
+                       (void)__bam_stkrel(dbp);
+               else
+                       DISCARD(dbp, cp);
                *cp = copy;
        }
 
@@ -976,7 +1021,7 @@ __bam_c_search(dbp, cp, key, flags, isrecno, exactp)
        DB *dbp;
        CURSOR *cp;
        const DBT *key;
-       u_int flags;
+       u_int32_t flags;
        int isrecno, *exactp;
 {
        BTREE *t;
@@ -1032,6 +1077,18 @@ __bam_c_search(dbp, cp, key, flags, isrecno, exactp)
                } else
                        if ((ret = __bam_c_next(dbp, cp, 0)) != 0)
                                return (ret);
+       /*
+        * If we don't specify an exact match (the DB_KEYFIRST/DB_KEYLAST or
+        * DB_SET_RANGE flags were set) __bam_search() may return a deleted
+        * item.  For DB_KEYFIRST/DB_KEYLAST, we don't care since we're only
+        * using it for a tree position.  For DB_SET_RANGE, we're returning
+        * the key, so we have to adjust it.
+        */
+       if (LF_ISSET(S_DELNO) && cp->dpgno == PGNO_INVALID &&
+           B_DISSET(GET_BKEYDATA(cp->page, cp->indx + O_INDX)->type))
+               if ((ret = __bam_c_next(dbp, cp, 0)) != 0)
+                       return (ret);
+
        return (0);
 }
 
@@ -1101,7 +1158,7 @@ __bam_cprint(dbp)
        CURSOR *cp;
        DBC *dbc;
 
-       DB_THREAD_LOCK(dbp);
+       CURSOR_SETUP(dbp);
        for (dbc = TAILQ_FIRST(&dbp->curs_queue);
            dbc != NULL; dbc = TAILQ_NEXT(dbc, links)) {
                cp = (CURSOR *)dbc->internal;
@@ -1113,7 +1170,8 @@ __bam_cprint(dbp)
                        fprintf(stderr, "(deleted)");
                fprintf(stderr, "\n");
        }
-       DB_THREAD_UNLOCK(dbp);
+       CURSOR_TEARDOWN(dbp);
+
        return (0);
 }
 #endif /* DEBUG */
@@ -1135,7 +1193,7 @@ __bam_ca_delete(dbp, pgno, indx, curs, key_delete)
 {
        DBC *dbc;
        CURSOR *cp;
-       int count;
+       int count;              /* !!!: Has to contain max number of cursors. */
 
        /*
         * Adjust the cursors.  We don't have to review the cursors for any
@@ -1148,8 +1206,7 @@ __bam_ca_delete(dbp, pgno, indx, curs, key_delete)
         * locks on the same page, but, cursors within a thread must be single
         * threaded, so all we're locking here is the cursor linked list.
         */
-       DB_THREAD_LOCK(dbp);
-
+       CURSOR_SETUP(dbp);
        for (count = 0, dbc = TAILQ_FIRST(&dbp->curs_queue);
            dbc != NULL; dbc = TAILQ_NEXT(dbc, links)) {
                cp = (CURSOR *)dbc->internal;
@@ -1180,8 +1237,8 @@ __bam_ca_delete(dbp, pgno, indx, curs, key_delete)
                                F_SET(cp, C_DELETED);
                        }
        }
+       CURSOR_TEARDOWN(dbp);
 
-       DB_THREAD_UNLOCK(dbp);
        return (count);
 }
 
@@ -1192,11 +1249,11 @@ __bam_ca_delete(dbp, pgno, indx, curs, key_delete)
  * PUBLIC: void __bam_ca_di __P((DB *, db_pgno_t, u_int32_t, int));
  */
 void
-__bam_ca_di(dbp, pgno, indx, value)
+__bam_ca_di(dbp, pgno, indx, adjust)
        DB *dbp;
        db_pgno_t pgno;
        u_int32_t indx;
-       int value;
+       int adjust;
 {
        CURSOR *cp;
        DBC *dbc;
@@ -1208,16 +1265,16 @@ __bam_ca_di(dbp, pgno, indx, value)
        /*
         * Adjust the cursors.  See the comment in __bam_ca_delete().
         */
-       DB_THREAD_LOCK(dbp);
+       CURSOR_SETUP(dbp);
        for (dbc = TAILQ_FIRST(&dbp->curs_queue);
            dbc != NULL; dbc = TAILQ_NEXT(dbc, links)) {
                cp = (CURSOR *)dbc->internal;
                if (cp->pgno == pgno && cp->indx >= indx)
-                       cp->indx += value;
+                       cp->indx += adjust;
                if (cp->dpgno == pgno && cp->dindx >= indx)
-                       cp->dindx += value;
+                       cp->dindx += adjust;
        }
-       DB_THREAD_UNLOCK(dbp);
+       CURSOR_TEARDOWN(dbp);
 }
 
 /*
@@ -1242,7 +1299,7 @@ __bam_ca_dup(dbp, fpgno, first, fi, tpgno, ti)
         * No need to test duplicates, this only gets called when moving
         * leaf page data items onto a duplicates page.
         */
-       DB_THREAD_LOCK(dbp);
+       CURSOR_SETUP(dbp);
        for (dbc = TAILQ_FIRST(&dbp->curs_queue);
            dbc != NULL; dbc = TAILQ_NEXT(dbc, links)) {
                cp = (CURSOR *)dbc->internal;
@@ -1258,7 +1315,7 @@ __bam_ca_dup(dbp, fpgno, first, fi, tpgno, ti)
                        cp->dindx = ti;
                }
        }
-       DB_THREAD_UNLOCK(dbp);
+       CURSOR_TEARDOWN(dbp);
 }
 
 /*
@@ -1285,14 +1342,14 @@ __bam_ca_move(dbp, fpgno, tpgno)
         * No need to test duplicates, this only gets called when copying
         * over the root page with a leaf or internal page.
         */
-       DB_THREAD_LOCK(dbp);
+       CURSOR_SETUP(dbp);
        for (dbc = TAILQ_FIRST(&dbp->curs_queue);
            dbc != NULL; dbc = TAILQ_NEXT(dbc, links)) {
                cp = (CURSOR *)dbc->internal;
                if (cp->pgno == fpgno)
                        cp->pgno = tpgno;
        }
-       DB_THREAD_UNLOCK(dbp);
+       CURSOR_TEARDOWN(dbp);
 }
 
 /*
@@ -1333,7 +1390,7 @@ __bam_ca_replace(dbp, pgno, indx, pass)
         * for the cursor as it may have been changed by other cursor update
         * routines as the item was deleted/inserted.
         */
-       DB_THREAD_LOCK(dbp);
+       CURSOR_SETUP(dbp);
        switch (pass) {
        case REPLACE_SETUP:                     /* Setup. */
                for (dbc = TAILQ_FIRST(&dbp->curs_queue);
@@ -1372,7 +1429,7 @@ __bam_ca_replace(dbp, pgno, indx, pass)
                }
                break;
        }
-       DB_THREAD_UNLOCK(dbp);
+       CURSOR_TEARDOWN(dbp);
 }
 
 /*
@@ -1406,7 +1463,7 @@ __bam_ca_split(dbp, ppgno, lpgno, rpgno, split_indx, cleft)
         * the cursor is on the right page, it is decremented by the number of
         * records split to the left page.
         */
-       DB_THREAD_LOCK(dbp);
+       CURSOR_SETUP(dbp);
        for (dbc = TAILQ_FIRST(&dbp->curs_queue);
            dbc != NULL; dbc = TAILQ_NEXT(dbc, links)) {
                cp = (CURSOR *)dbc->internal;
@@ -1427,7 +1484,7 @@ __bam_ca_split(dbp, ppgno, lpgno, rpgno, split_indx, cleft)
                                cp->dindx -= split_indx;
                        }
        }
-       DB_THREAD_UNLOCK(dbp);
+       CURSOR_TEARDOWN(dbp);
 }
 
 /*
@@ -1440,16 +1497,17 @@ __bam_c_physdel(dbp, cp, h)
        CURSOR *cp;
        PAGE *h;
 {
+       enum { DELETE_ITEM, DELETE_PAGE, NOTHING_FURTHER } cmd;
        BOVERFLOW bo;
        BTREE *t;
        DBT dbt;
        DB_LOCK lock;
        db_indx_t indx;
        db_pgno_t pgno, next_pgno, prev_pgno;
-       int local, normal, ret;
+       int delete_page, local_page, ret;
 
        t = dbp->internal;
-       ret = 0;
+       delete_page = ret = 0;
 
        /* Figure out what we're deleting. */
        if (cp->dpgno == PGNO_INVALID) {
@@ -1476,9 +1534,9 @@ __bam_c_physdel(dbp, cp, h)
                        return (ret);
                if ((ret = __bam_pget(dbp, &h, &pgno, 0)) != 0)
                        return (ret);
-               local = 1;
+               local_page = 1;
        } else
-               local = 0;
+               local_page = 0;
 
        /*
         * If we're deleting a duplicate entry and there are other duplicate
@@ -1515,9 +1573,9 @@ __bam_c_physdel(dbp, cp, h)
 
                if (NUM_ENT(h) == 1 &&
                    prev_pgno == PGNO_INVALID && next_pgno == PGNO_INVALID)
-                       normal = 1;
+                       cmd = DELETE_PAGE;
                else {
-                       normal = 0;
+                       cmd = DELETE_ITEM;
 
                        /* Delete the duplicate. */
                        if ((ret = __db_drem(dbp, &h, indx, __bam_free)) != 0)
@@ -1536,18 +1594,27 @@ __bam_c_physdel(dbp, cp, h)
                         */
                        if ((h != NULL && pgno == h->pgno) ||
                            prev_pgno != PGNO_INVALID)
-                               goto done;
+                               cmd = NOTHING_FURTHER;
                }
 
-               /* Release any page we're holding and its lock. */
-               if (local) {
+               /*
+                * Release any page we're holding and its lock.
+                *
+                * !!!
+                * If there is no subsequent page in the duplicate chain, then
+                * __db_drem will have put page "h" and set it to NULL.
+               */
+               if (local_page) {
                        if (h != NULL)
                                (void)memp_fput(dbp->mpf, h, 0);
                        (void)__BT_TLPUT(dbp, lock);
-                       local = 0;
+                       local_page = 0;
                }
 
-               /* Acquire the parent page. */
+               if (cmd == NOTHING_FURTHER)
+                       goto done;
+
+               /* Acquire the parent page and switch the index to its entry. */
                if ((ret =
                    __bam_lget(dbp, 0, cp->pgno, DB_LOCK_WRITE, &lock)) != 0)
                        goto err;
@@ -1555,11 +1622,10 @@ __bam_c_physdel(dbp, cp, h)
                        (void)__BT_TLPUT(dbp, lock);
                        goto err;
                }
-               local = 1;
-
-               /* Switch to the parent page's entry. */
+               local_page = 1;
                indx = cp->indx;
-               if (normal)
+
+               if (cmd == DELETE_PAGE)
                        goto btd;
 
                /*
@@ -1582,47 +1648,60 @@ __bam_c_physdel(dbp, cp, h)
                goto done;
        }
 
-       /* Otherwise, do a normal btree delete. */
-btd:   if ((ret = __bam_ditem(dbp, h, indx)) != 0)
-               goto err;
-       if ((ret = __bam_ditem(dbp, h, indx)) != 0)
-               goto err;
-
-       /*
-        * If the page is empty, delete it.  To delete a leaf page we need a
-        * copy of a key from the page.  We use the first one that was there,
-        * since it's the last key that the page held.  We malloc the page
-        * information instead of using the return key/data memory because
-        * we've already set them -- the reason that we've already set them
-        * is because we're (potentially) about to do a reverse split, which
-        * would make our saved page information useless.
+btd:   /*
+        * If the page is going to be emptied, delete it.  To delete a leaf
+        * page we need a copy of a key from the page.  We use the 0th page
+        * index since it's the last key that the page held.
+        *
+        * We malloc the page information instead of using the return key/data
+        * memory because we've already set them -- the reason we've already
+        * set them is because we're (potentially) about to do a reverse split,
+        * which would make our saved page information useless.
         *
         * XXX
         * The following operations to delete a page might deadlock.  I think
         * that's OK.  The problem is if we're deleting an item because we're
         * closing cursors because we've already deadlocked and want to call
-        * txn_abort().  If we fail due to deadlock, we'll leave an locked
-        * empty page in the tree, which won't be empty long because we're
-        * going to undo the delete.
+        * txn_abort().  If we fail due to deadlock, we leave a locked empty
+        * page in the tree, which won't be empty long because we're going to
+        * undo the delete.
         */
-       if (NUM_ENT(h) == 0 && h->pgno != PGNO_ROOT) {
+       if (NUM_ENT(h) == 2 && h->pgno != PGNO_ROOT) {
                memset(&dbt, 0, sizeof(DBT));
                dbt.flags = DB_DBT_MALLOC | DB_DBT_INTERNAL;
                if ((ret = __db_ret(dbp, h, 0, &dbt, NULL, NULL)) != 0)
                        goto err;
+               delete_page = 1;
+       }
 
-               if (local) {
-                       (void)memp_fput(dbp->mpf, h, 0);
-                       (void)__BT_TLPUT(dbp, lock);
-                       local = 0;
-               }
+       /*
+        * Do a normal btree delete.
+        *
+        * XXX
+        * Delete the key item first, otherwise the duplicate checks in
+        * __bam_ditem() won't work!
+        */
+       if ((ret = __bam_ditem(dbp, h, indx)) != 0)
+               goto err;
+       if ((ret = __bam_ditem(dbp, h, indx)) != 0)
+               goto err;
 
-               ret = __bam_dpage(dbp, &dbt);
-               __db_free(dbt.data);
+       /* Discard any remaining locks/pages. */
+       if (local_page) {
+               (void)memp_fput(dbp->mpf, h, 0);
+               (void)__BT_TLPUT(dbp, lock);
+               local_page = 0;
        }
 
+       /* Delete the page if it was emptied. */
+       if (delete_page)
+               ret = __bam_dpage(dbp, &dbt);
+
 err:
-done:  if (local) {
+done:  if (delete_page)
+               __db_free(dbt.data);
+
+       if (local_page) {
                (void)memp_fput(dbp->mpf, h, 0);
                (void)__BT_TLPUT(dbp, lock);
        }
@@ -1631,3 +1710,43 @@ done:    if (local) {
                ++t->lstat.bt_deleted;
        return (ret);
 }
+
+/*
+ * __bam_c_getstack --
+ *     Acquire a full stack for a cursor.
+ */
+static int
+__bam_c_getstack(dbp, cp)
+       DB *dbp;
+       CURSOR *cp;
+{
+       DBT dbt;
+       PAGE *h;
+       db_pgno_t pgno;
+       int exact, ret;
+
+       ret = 0;
+       h = NULL;
+       memset(&dbt, 0, sizeof(DBT));
+
+       /* Get the page with the current item on it. */
+       pgno = cp->pgno;
+       if ((ret = __bam_pget(dbp, &h, &pgno, 0)) != 0)
+               return (ret);
+
+       /* Get a copy of a key from the page. */
+       dbt.flags = DB_DBT_MALLOC | DB_DBT_INTERNAL;
+       if ((ret = __db_ret(dbp, h, 0, &dbt, NULL, NULL)) != 0)
+               goto err;
+
+       /* Get a write-locked stack for that page. */
+       exact = 0;
+       ret = __bam_search(dbp, &dbt, S_KEYFIRST, 1, NULL, &exact);
+
+       /* We no longer need the key or the page. */
+err:   if (h != NULL)
+               (void)memp_fput(dbp->mpf, h, 0);
+       if (dbt.data != NULL)
+               __db_free(dbt.data);
+       return (ret);
+}
index baa8a25..7e71037 100644 (file)
@@ -1,7 +1,7 @@
 /*-
  * See the file LICENSE for redistribution information.
  *
- * Copyright (c) 1996, 1997
+ * Copyright (c) 1996, 1997, 1998
  *     Sleepycat Software.  All rights reserved.
  */
 /*
 #include "config.h"
 
 #ifndef lint
-static const char sccsid[] = "@(#)bt_delete.c  10.25 (Sleepycat) 1/8/98";
+static const char sccsid[] = "@(#)bt_delete.c  10.31 (Sleepycat) 5/6/98";
 #endif /* not lint */
 
 #ifndef NO_SYSTEM_INCLUDES
 #include <sys/types.h>
 
-#include <stdio.h>
 #include <string.h>
 #endif
 
@@ -67,14 +66,14 @@ static int __bam_dpages __P((DB *, BTREE *));
  * __bam_delete --
  *     Delete the items referenced by a key.
  *
- * PUBLIC: int __bam_delete __P((DB *, DB_TXN *, DBT *, int));
+ * PUBLIC: int __bam_delete __P((DB *, DB_TXN *, DBT *, u_int32_t));
  */
 int
 __bam_delete(argdbp, txn, key, flags)
        DB *argdbp;
        DB_TXN *txn;
        DBT *key;
-       int flags;
+       u_int32_t flags;
 {
        BTREE *t;
        DB *dbp;
@@ -87,8 +86,8 @@ __bam_delete(argdbp, txn, key, flags)
        stack = 0;
 
        /* Check for invalid flags. */
-       if ((ret =
-           __db_delchk(argdbp, flags, F_ISSET(argdbp, DB_AM_RDONLY))) != 0)
+       if ((ret = __db_delchk(argdbp,
+           key, flags, F_ISSET(argdbp, DB_AM_RDONLY))) != 0)
                return (ret);
 
        GETHANDLE(argdbp, txn, &dbp, ret);
@@ -107,6 +106,11 @@ __bam_delete(argdbp, txn, key, flags)
                        break;
        for (; cnt > 0; --cnt, ++t->lstat.bt_deleted)
                if (__bam_ca_delete(dbp, h->pgno, indx, NULL, 1) == 0) {
+                       /*
+                        * XXX
+                        * Delete the key item first, otherwise the duplicate
+                        * checks in __bam_ditem() won't work!
+                        */
                        if ((ret = __bam_ditem(dbp, h, indx)) != 0)
                                goto err;
                        if ((ret = __bam_ditem(dbp, h, indx)) != 0)
@@ -138,14 +142,14 @@ err:      if (stack)
  * __ram_delete --
  *     Delete the items referenced by a key.
  *
- * PUBLIC: int __ram_delete __P((DB *, DB_TXN *, DBT *, int));
+ * PUBLIC: int __ram_delete __P((DB *, DB_TXN *, DBT *, u_int32_t));
  */
 int
 __ram_delete(argdbp, txn, key, flags)
        DB *argdbp;
        DB_TXN *txn;
        DBT *key;
-       int flags;
+       u_int32_t flags;
 {
        BKEYDATA bk;
        BTREE *t;
@@ -159,8 +163,8 @@ __ram_delete(argdbp, txn, key, flags)
        stack = 0;
 
        /* Check for invalid flags. */
-       if ((ret =
-           __db_delchk(argdbp, flags, F_ISSET(argdbp, DB_AM_RDONLY))) != 0)
+       if ((ret = __db_delchk(argdbp,
+           key, flags, F_ISSET(argdbp, DB_AM_RDONLY))) != 0)
                return (ret);
 
        GETHANDLE(argdbp, txn, &dbp, ret);
@@ -284,19 +288,32 @@ __bam_ditem(dbp, h, indx)
        case P_LBTREE:
                /*
                 * If it's a duplicate key, discard the index and don't touch
-                * the actual page item.  This works because no data item can
-                * have an index that matches any other index so even if the
-                * data item is in an index "slot", it won't match any other
-                * index.
+                * the actual page item.
+                *
+                * XXX
+                * This works because no data item can have an index matching
+                * any other index so even if the data item is in a key "slot",
+                * it won't match any other index.
                 */
-               if (!(indx % 2)) {
-                       if (indx > 0 && h->inp[indx] == h->inp[indx - P_INDX])
-                               return (__bam_adjindx(dbp,
-                                   h, indx, indx - P_INDX, 0));
+               if ((indx % 2) == 0) {
+                       /*
+                        * Check for a duplicate after us on the page.  NOTE:
+                        * we have to delete the key item before deleting the
+                        * data item, otherwise the "indx + P_INDX" calculation
+                        * won't work!
+                        */
                        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));
+                       /*
+                        * Check for a duplicate before us on the page.  It
+                        * doesn't matter if we delete the key item before or
+                        * after the data item for the purposes of this one.
+                        */
+                       if (indx > 0 && h->inp[indx] == h->inp[indx - P_INDX])
+                               return (__bam_adjindx(dbp,
+                                   h, indx, indx - P_INDX, 0));
                }
                /* FALLTHROUGH */
        case P_LRECNO:
@@ -396,7 +413,8 @@ __bam_dpage(dbp, key)
        DB_LOCK lock;
        PAGE *h;
        db_pgno_t pgno;
-       int exact, level, ret;
+       int level;              /* !!!: has to hold number of tree levels. */
+       int exact, ret;
 
        ret = 0;
        t = dbp->internal;
@@ -527,13 +545,14 @@ __bam_dpages(dbp, t)
                goto release;
 
        /*
-        * If we deleted the next-to-last item from the root page, the tree
-        * 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.
+        * If we just deleted the last or next-to-last item from the root page,
+        * the tree can collapse a level.  Write lock the last page referenced
+        * by the root page and copy it over the root page.  If we can't get a
+        * write lock, that's okay, the tree just remains a level deeper than
+        * we'd like.
         */
        h = epg->page;
-       if (h->pgno == PGNO_ROOT && NUM_ENT(h) == 1) {
+       if (h->pgno == PGNO_ROOT && NUM_ENT(h) <= 1) {
                pgno = TYPE(epg->page) == P_IBTREE ?
                    GET_BINTERNAL(epg->page, 0)->pgno :
                    GET_RINTERNAL(epg->page, 0)->pgno;
@@ -573,13 +592,21 @@ __bam_dpages(dbp, t)
                (void)memp_fset(dbp->mpf, epg->page, DB_MPOOL_DIRTY);
 
                /*
-                * Free the last page in that level of the btree and discard
-                * the lock.  (The call to __bam_free discards our reference
+                * Free the page copied onto the root page and discard its
+                * lock.  (The call to __bam_free() discards our reference
                 * to the page.)
+                *
+                * It's possible that the reverse split we're doing involves
+                * pages from the stack of pages we're deleting.  Don't free
+                * the page twice.
                 */
-               (void)__bam_free(dbp, h);
+                if (h->pgno == (epg + 1)->page->pgno)
+                       (void)memp_fput(dbp->mpf, h, 0);
+               else {
+                       (void)__bam_free(dbp, h);
+                       ++t->lstat.bt_freed;
+               }
                (void)__BT_TLPUT(dbp, lock);
-               ++t->lstat.bt_freed;
 
                /* Adjust the cursors. */
                __bam_ca_move(dbp, h->pgno, PGNO_ROOT);
@@ -596,12 +623,17 @@ __bam_dpages(dbp, t)
         * Don't bother checking for errors.  We've unlinked the subtree from
         * the tree, and there's no possibility of recovery.
         */
-       for (; ++epg <= t->bt_csp; ++t->lstat.bt_freed) {
+       while (++epg <= t->bt_csp) {
+               /*
+                * XXX
+                * Why do we need to do this?  Isn't the page already empty?
+                */
                if (NUM_ENT(epg->page) != 0)
                        (void)__bam_ditem(dbp, epg->page, epg->indx);
 
                (void)__bam_free(dbp, epg->page);
                (void)__BT_TLPUT(dbp, epg->lock);
+               ++t->lstat.bt_freed;
        }
        return (0);
 
index dd9f109..f5974ec 100644 (file)
@@ -1,7 +1,7 @@
 /*-
  * See the file LICENSE for redistribution information.
  *
- * Copyright (c) 1996, 1997
+ * Copyright (c) 1996, 1997, 1998
  *     Sleepycat Software.  All rights reserved.
  */
 /*
@@ -47,7 +47,7 @@
 #include "config.h"
 
 #ifndef lint
-static const char sccsid[] = "@(#)bt_open.c    10.22 (Sleepycat) 1/6/98";
+static const char sccsid[] = "@(#)bt_open.c    10.27 (Sleepycat) 5/6/98";
 #endif /* not lint */
 
 /*
@@ -60,21 +60,15 @@ static const char sccsid[] = "@(#)bt_open.c 10.22 (Sleepycat) 1/6/98";
 
 #ifndef NO_SYSTEM_INCLUDES
 #include <sys/types.h>
-#include <sys/stat.h>
 
 #include <errno.h>
-#include <fcntl.h>
 #include <limits.h>
-#include <stdio.h>
-#include <stdlib.h>
 #include <string.h>
-#include <unistd.h>
 #endif
 
 #include "db_int.h"
 #include "db_page.h"
 #include "btree.h"
-#include "common_ext.h"
 
 static int __bam_keyalloc __P((BTREE *));
 static int __bam_setmeta __P((DB *, BTREE *));
@@ -295,6 +289,7 @@ __bam_setmeta(dbp, t)
        }
 
        /* Initialize the tree structure metadata information. */
+       memset(meta, 0, sizeof(BTMETA));
        ZERO_LSN(meta->lsn);
        meta->pgno = PGNO_METADATA;
        meta->magic = DB_BTREEMAGIC;
@@ -303,7 +298,6 @@ __bam_setmeta(dbp, t)
        meta->maxkey = t->bt_maxkey;
        meta->minkey = t->bt_minkey;
        meta->free = PGNO_INVALID;
-       meta->flags = 0;
        if (dbp->type == DB_RECNO)
                F_SET(meta, BTM_RECNO);
        if (F_ISSET(dbp, DB_AM_DUP))
@@ -314,8 +308,6 @@ __bam_setmeta(dbp, t)
                F_SET(meta, BTM_RECNUM);
        if (F_ISSET(dbp, DB_RE_RENUMBER))
                F_SET(meta, BTM_RENUMBER);
-       meta->re_len = 0;
-       meta->re_pad = 0;
        memcpy(meta->uid, dbp->lock.fileid, DB_FILE_ID_LEN);
 
        /* Create and initialize a root page. */
index 853317e..87f2811 100644 (file)
@@ -1,7 +1,7 @@
 /*-
  * See the file LICENSE for redistribution information.
  *
- * Copyright (c) 1996, 1997
+ * Copyright (c) 1996, 1997, 1998
  *     Sleepycat Software.  All rights reserved.
  */
 /*
 #include "config.h"
 
 #ifndef lint
-static const char sccsid[] = "@(#)bt_page.c    10.7 (Sleepycat) 1/7/98";
+static const char sccsid[] = "@(#)bt_page.c    10.12 (Sleepycat) 5/6/98";
 #endif /* not lint */
 
 #ifndef NO_SYSTEM_INCLUDES
 #include <sys/types.h>
 
 #include <errno.h>
-#include <stdio.h>
 #include <string.h>
 #endif
 
@@ -142,7 +141,8 @@ __bam_free(dbp, h)
        DBT ldbt;
        DB_LOCK metalock;
        db_pgno_t pgno;
-       int is_dirty, ret, t_ret;
+       u_int32_t dirty_flag;
+       int ret, t_ret;
 
        /*
         * Retrieve the metadata page and insert the page at the head of
@@ -150,7 +150,7 @@ __bam_free(dbp, h)
         * fail, then we need to put the page with which we were called
         * back because our caller assumes we take care of it.
         */
-       is_dirty = 0;
+       dirty_flag = 0;
        pgno = PGNO_METADATA;
        if ((ret = __bam_lget(dbp, 0, pgno, DB_LOCK_WRITE, &metalock)) != 0)
                goto err;
@@ -178,7 +178,7 @@ __bam_free(dbp, h)
         * The page should have nothing interesting on it, re-initialize it,
         * leaving only the page number and the LSN.
         */
-#ifdef DEBUG
+#ifdef DIAGNOSTIC
        { db_pgno_t __pgno; DB_LSN __lsn;
                __pgno = h->pgno;
                __lsn = h->lsn;
@@ -198,8 +198,8 @@ __bam_free(dbp, h)
                ret = t_ret;
 
        /* Discard the caller's page reference. */
-       is_dirty = DB_MPOOL_DIRTY;
-err:   if ((t_ret = memp_fput(dbp->mpf, h, is_dirty)) != 0 && ret == 0)
+       dirty_flag = DB_MPOOL_DIRTY;
+err:   if ((t_ret = memp_fput(dbp->mpf, h, dirty_flag)) != 0 && ret == 0)
                ret = t_ret;
 
        /*
@@ -248,8 +248,10 @@ __bam_lget(dbp, do_couple, pgno, mode, lockp)
        u_int32_t locker;
        int ret;
 
-       if (!F_ISSET(dbp, DB_AM_LOCKING))
+       if (!F_ISSET(dbp, DB_AM_LOCKING)) {
+               *lockp = LOCK_INVALID;
                return (0);
+       }
 
        locker = dbp->txn == NULL ? dbp->locker : dbp->txn->txnid;
        dbp->lock.pgno = pgno;
@@ -300,15 +302,15 @@ __bam_lput(dbp, lock)
  * __bam_pget --
  *     The standard page get call.
  *
- * PUBLIC: int __bam_pget __P((DB *, PAGE **, db_pgno_t *, int));
+ * PUBLIC: int __bam_pget __P((DB *, PAGE **, db_pgno_t *, u_int32_t));
  */
 int
-__bam_pget(dbp, hp, pgnop, mflags)
+__bam_pget(dbp, hp, pgnop, mpool_flags)
        DB *dbp;
        PAGE **hp;
        db_pgno_t *pgnop;
-       int mflags;
+       u_int32_t mpool_flags;
 {
        return (memp_fget((dbp)->mpf,
-           pgnop, mflags, hp) == 0 ? 0 : __db_pgerr(dbp, *pgnop));
+           pgnop, mpool_flags, hp) == 0 ? 0 : __db_pgerr(dbp, *pgnop));
 }
index 87f3fd9..a93faac 100644 (file)
@@ -1,7 +1,7 @@
 /*-
  * See the file LICENSE for redistribution information.
  *
- * Copyright (c) 1996, 1997
+ * Copyright (c) 1996, 1997, 1998
  *     Sleepycat Software.  All rights reserved.
  */
 /*
 #include "config.h"
 
 #ifndef lint
-static const char sccsid[] = "@(#)bt_put.c     10.38 (Sleepycat) 1/8/98";
+static const char sccsid[] = "@(#)bt_put.c     10.45 (Sleepycat) 5/25/98";
 #endif /* not lint */
 
 #ifndef NO_SYSTEM_INCLUDES
 #include <sys/types.h>
 
 #include <errno.h>
-#include <stdio.h>
-#include <stdlib.h>
 #include <string.h>
 #endif
 
@@ -75,21 +73,22 @@ static u_int32_t __bam_partsize __P((DBT *, PAGE *, u_int32_t));
  * __bam_put --
  *     Add a new key/data pair or replace an existing pair (btree).
  *
- * PUBLIC: int __bam_put __P((DB *, DB_TXN *, DBT *, DBT *, int));
+ * PUBLIC: int __bam_put __P((DB *, DB_TXN *, DBT *, DBT *, u_int32_t));
  */
 int
 __bam_put(argdbp, txn, key, data, flags)
        DB *argdbp;
        DB_TXN *txn;
        DBT *key, *data;
-       int flags;
+       u_int32_t flags;
 {
        BTREE *t;
        CURSOR c;
        DB *dbp;
        PAGE *h;
        db_indx_t indx;
-       int exact, iflags, isdeleted, newkey, replace, ret, stack;
+       u_int32_t iitem_flags, insert_flags;
+       int exact, isdeleted, newkey, ret, stack;
 
        DEBUG_LWRITE(argdbp, txn, "bam_put", key, data, flags);
 
@@ -121,14 +120,13 @@ retry:    /*
         * been marked for deletion, we do a replace, otherwise, it has to be
         * a set of duplicates, and we simply append a new one to the set.
         */
-       isdeleted = replace = 0;
+       isdeleted = 0;
        if (exact) {
                if ((ret = __bam_isdeleted(dbp, h, indx, &isdeleted)) != 0)
                        goto err;
-               if (isdeleted) {
-                       replace = 1;
+               if (isdeleted)
                        __bam_ca_replace(dbp, h->pgno, indx, REPLACE_SETUP);
-               else
+               else
                        if (flags == DB_NOOVERWRITE) {
                                ret = DB_KEYEXIST;
                                goto err;
@@ -179,42 +177,38 @@ retry:    /*
                                t->bt_csp->page = h = c.page;
                                indx = c.dindx;
                        }
-                       iflags = DB_AFTER;
+                       insert_flags = DB_AFTER;
                } else
-                       iflags = DB_CURRENT;
+                       insert_flags = DB_CURRENT;
        } else
-               iflags = DB_BEFORE;
+               insert_flags = DB_BEFORE;
 
        /*
         * The pages we're using may be modified by __bam_iitem(), so make
         * sure we reset the stack.
         */
-       ret = __bam_iitem(dbp,
-           &h, &indx, key, data, iflags, newkey ? BI_NEWKEY : 0);
+       iitem_flags = 0;
+       if (newkey)
+               iitem_flags |= BI_NEWKEY;
+       if (isdeleted)
+               iitem_flags |= BI_DOINCR;
+       ret = __bam_iitem(dbp, &h, &indx, key, data, insert_flags, iitem_flags);
        t->bt_csp->page = h;
        t->bt_csp->indx = indx;
 
        switch (ret) {
        case 0:
-               /*
-                * Done.  Clean up the cursor, and, if we're doing record
-                * numbers, adjust the internal page counts.
-                */
-               if (replace)
+               /* Done.  Clean up the cursor. */
+               if (isdeleted)
                        __bam_ca_replace(dbp, h->pgno, indx, REPLACE_SUCCESS);
-
-               if (!replace && F_ISSET(dbp, DB_BT_RECNUM))
-                       ret = __bam_adjust(dbp, t, 1);
                break;
        case DB_NEEDSPLIT:
                /*
                 * We have to split the page.  Back out the cursor setup,
                 * discard the stack of pages, and do the split.
                 */
-               if (replace) {
-                       replace = 0;
+               if (isdeleted)
                        __bam_ca_replace(dbp, h->pgno, indx, REPLACE_FAILED);
-               }
 
                (void)__bam_stkrel(dbp);
                stack = 0;
@@ -225,7 +219,7 @@ retry:      /*
                goto retry;
                /* NOTREACHED */
        default:
-               if (replace)
+               if (isdeleted)
                        __bam_ca_replace(dbp, h->pgno, indx, REPLACE_FAILED);
                break;
        }
@@ -393,7 +387,8 @@ __bam_lookup(dbp, key, exactp)
                                for (indx = 0;
                                    indx < (db_indx_t)(NUM_ENT(h) - P_INDX) &&
                                    h->inp[indx] == h->inp[indx + P_INDX];
-                                   indx += P_INDX);
+                                   indx += P_INDX)
+                                       ;
                                e.indx = indx;
                        }
                        goto fast;
@@ -427,7 +422,7 @@ slow:       return (__bam_search(dbp, key, S_INSERT, 1, NULL, exactp));
  *     Insert an item into the tree.
  *
  * PUBLIC: int __bam_iitem __P((DB *,
- * PUBLIC:    PAGE **, db_indx_t *, DBT *, DBT *, int, int));
+ * PUBLIC:    PAGE **, db_indx_t *, DBT *, DBT *, u_int32_t, u_int32_t));
  */
 int
 __bam_iitem(dbp, hp, indxp, key, data, op, flags)
@@ -435,13 +430,13 @@ __bam_iitem(dbp, hp, indxp, key, data, op, flags)
        PAGE **hp;
        db_indx_t *indxp;
        DBT *key, *data;
-       int op, flags;
+       u_int32_t op, flags;
 {
        BTREE *t;
        BKEYDATA *bk;
        DBT tdbt;
        PAGE *h;
-       db_indx_t indx;
+       db_indx_t indx, nbytes;
        u_int32_t data_size, have_bytes, need_bytes, needed;
        int bigkey, bigdata, dupadjust, replace, ret;
 
@@ -466,12 +461,27 @@ __bam_iitem(dbp, hp, indxp, key, data, op, flags)
                        ++*indxp;
 
                /* Remove the current item if it's a DB_CURRENT op. */
-               if (op == DB_CURRENT && (ret = __db_ditem(dbp, *hp, *indxp,
-                   BKEYDATA_SIZE(GET_BKEYDATA(*hp, *indxp)->len))) != 0)
-                       return (ret);
+               if (op == DB_CURRENT) {
+                       bk = GET_BKEYDATA(*hp, *indxp);
+                       switch (B_TYPE(bk->type)) {
+                       case B_KEYDATA:
+                               nbytes = BKEYDATA_SIZE(bk->len);
+                               break;
+                       case B_OVERFLOW:
+                               nbytes = BOVERFLOW_SIZE;
+                               break;
+                       default:
+                               return (__db_pgfmt(dbp, h->pgno));
+                       }
+                       if ((ret = __db_ditem(dbp, *hp, *indxp, nbytes)) != 0)
+                               return (ret);
+               }
 
                /* Put the new/replacement item onto the page. */
-               return (__db_dput(dbp, data, hp, indxp, __bam_new));
+               if ((ret = __db_dput(dbp, data, hp, indxp, __bam_new)) != 0)
+                       return (ret);
+
+               goto done;
        }
 
        /* Handle fixed-length records: build the real record. */
@@ -568,7 +578,7 @@ __bam_iitem(dbp, hp, indxp, key, data, op, flags)
                case DB_BEFORE:         /* 2. Insert a new key/data pair. */
                        break;
                default:
-                       abort();
+                       return (EINVAL);
                }
 
                /* Add the key. */
@@ -638,7 +648,7 @@ __bam_iitem(dbp, hp, indxp, key, data, op, flags)
                        replace = 1;
                        break;
                default:
-                       abort();
+                       return (EINVAL);
                }
        }
 
@@ -666,9 +676,8 @@ __bam_iitem(dbp, hp, indxp, key, data, op, flags)
                        return (ret);
        }
 
-       ++t->lstat.bt_added;
-
-       ret = memp_fset(dbp->mpf, h, DB_MPOOL_DIRTY);
+       if ((ret = memp_fset(dbp->mpf, h, DB_MPOOL_DIRTY)) != 0)
+               return (ret);
 
        /*
         * If the page is at least 50% full, and we added a duplicate, see if
@@ -681,9 +690,25 @@ __bam_iitem(dbp, hp, indxp, key, data, op, flags)
                        return (ret);
        }
 
+       /*
+        * If we've changed the record count, update the tree.  Record counts
+        * need to be updated in recno databases and in btree databases where
+        * we are supporting records.  In both cases, adjust the count if the
+        * operation wasn't performed on the current record or when the caller
+        * overrides and wants the adjustment made regardless.
+        */
+done:  if (LF_ISSET(BI_DOINCR) ||
+           (op != DB_CURRENT &&
+           (F_ISSET(dbp, DB_BT_RECNUM) || dbp->type == DB_RECNO)))
+               if ((ret = __bam_adjust(dbp, t, 1)) != 0)
+                       return (ret);
+
+       /* If we've modified a recno file, set the flag */
        if (t->bt_recno != NULL)
                F_SET(t->bt_recno, RECNO_MODIFIED);
 
+       ++t->lstat.bt_added;
+
        return (ret);
 }
 
@@ -1036,8 +1061,8 @@ __bam_partial(dbp, dbt, h, indx, nbytes)
        BOVERFLOW *bo;
        DBT copy;
        u_int32_t len, tlen;
-       int ret;
        u_int8_t *p;
+       int ret;
 
        COMPQUIET(bo, NULL);
 
@@ -1065,59 +1090,62 @@ __bam_partial(dbp, dbt, h, indx, nbytes)
                bk->len = 0;
        }
 
-       /* We use nul bytes for extending the record, get it over with. */
+       /*
+        * We use nul bytes for any part of the record that isn't specified,
+        * get it over with.
+        */
        memset(t->bt_rdata.data, 0, nbytes);
 
-       tlen = 0;
        if (B_TYPE(bk->type) == B_OVERFLOW) {
-               /* Take up to doff bytes from the record. */
+               /*
+                * In the case of an overflow record, we shift things around
+                * in the current record rather than allocate a separate copy.
+                */
                memset(&copy, 0, sizeof(copy));
                if ((ret = __db_goff(dbp, &copy, bo->tlen,
                    bo->pgno, &t->bt_rdata.data, &t->bt_rdata.ulen)) != 0)
                        return (ret);
-               tlen += dbt->doff;
+
+               /* Skip any leading data from the original record. */
+               tlen = dbt->doff;
+               p = (u_int8_t *)t->bt_rdata.data + dbt->doff;
 
                /*
-                * If the original record was larger than the offset:
-                *      If dlen > size, shift the remaining data down.
-                *      If dlen < size, shift the remaining data up.
+                * Copy in any trailing data from the original record.
+                *
+                * If the original record was larger than the original offset
+                * plus the bytes being deleted, there is trailing data in the
+                * original record we need to preserve.  If we aren't deleting
+                * the same number of bytes as we're inserting, copy it up or
+                * down, into place.
+                *
                 * Use memmove(), the regions may overlap.
                 */
-               p = t->bt_rdata.data;
-               if (bo->tlen > dbt->doff)
-                       if (dbt->dlen > dbt->size) {
-                               tlen += len = bo->tlen -
-                                   dbt->doff - (dbt->dlen - dbt->size);
-                               memmove(p + dbt->doff + dbt->size,
-                                   p + dbt->doff + dbt->dlen, len);
-                       } else if (dbt->dlen < dbt->size) {
-                               tlen += len = bo->tlen -
-                                   dbt->doff - (dbt->size - dbt->dlen);
-                               memmove(p + dbt->doff + dbt->dlen,
-                                   p + dbt->doff + dbt->size, len);
-                       } else
-                               tlen += bo->tlen - dbt->doff;
+               if (bo->tlen > dbt->doff + dbt->dlen) {
+                       len = bo->tlen - (dbt->doff + dbt->dlen);
+                       if (dbt->dlen != dbt->size)
+                               memmove(p + dbt->size, p + dbt->dlen, len);
+                       tlen += len;
+               }
 
-               /* Copy in the user's data. */
-               memcpy((u_int8_t *)t->bt_rdata.data + dbt->doff,
-                   dbt->data, dbt->size);
+               /* Copy in the application provided data. */
+               memcpy(p, dbt->data, dbt->size);
                tlen += dbt->size;
        } else {
-               /* Take up to doff bytes from the record. */
+               /* Copy in any leading data from the original record. */
                memcpy(t->bt_rdata.data,
                    bk->data, dbt->doff > bk->len ? bk->len : dbt->doff);
-               tlen += dbt->doff;
+               tlen = dbt->doff;
+               p = (u_int8_t *)t->bt_rdata.data + dbt->doff;
 
-               /* Copy in the user's data. */
-               memcpy((u_int8_t *)t->bt_rdata.data +
-                   dbt->doff, dbt->data, dbt->size);
+               /* Copy in the application provided data. */
+               memcpy(p, dbt->data, dbt->size);
                tlen += dbt->size;
 
-               /* Copy in any remaining data. */
+               /* Copy in any trailing data from the original record. */
                len = dbt->doff + dbt->dlen;
                if (bk->len > len) {
-                       memcpy((u_int8_t *)t->bt_rdata.data + dbt->doff +
-                           dbt->size, bk->data + len, bk->len - len);
+                       memcpy(p + dbt->size, bk->data + len, bk->len - len);
                        tlen += bk->len - len;
                }
        }
index 90ee137..fe33825 100644 (file)
@@ -1,23 +1,20 @@
 /*-
  * See the file LICENSE for redistribution information.
  *
- * Copyright (c) 1996, 1997
+ * Copyright (c) 1996, 1997, 1998
  *     Sleepycat Software.  All rights reserved.
  */
 
 #include "config.h"
 
 #ifndef lint
-static const char sccsid[] = "@(#)bt_rec.c     10.18 (Sleepycat) 12/15/97";
+static const char sccsid[] = "@(#)bt_rec.c     10.21 (Sleepycat) 4/28/98";
 #endif /* not lint */
 
 #ifndef NO_SYSTEM_INCLUDES
 #include <sys/types.h>
 
-#include <ctype.h>
 #include <errno.h>
-#include <stddef.h>
-#include <stdlib.h>
 #include <string.h>
 #endif
 
@@ -27,7 +24,6 @@ static const char sccsid[] = "@(#)bt_rec.c    10.18 (Sleepycat) 12/15/97";
 #include "hash.h"
 #include "btree.h"
 #include "log.h"
-#include "db_dispatch.h"
 #include "common_ext.h"
 
 /*
@@ -51,7 +47,7 @@ __bam_pg_alloc_recover(logp, dbtp, lsnp, redo, info)
        PAGE *pagep;
        DB *file_dbp, *mdbp;
        db_pgno_t pgno;
-       int cmp_n, cmp_p, created, modified, ret;
+       int cmp_n, cmp_p, modified, ret;
 
        REC_PRINT(__bam_pg_alloc_print);
        REC_INTRO(__bam_pg_alloc_read);
@@ -86,18 +82,17 @@ __bam_pg_alloc_recover(logp, dbtp, lsnp, redo, info)
        }
 
        /* Fix up the allocated page. */
-       created = IS_ZERO_LSN(LSN(pagep));
        modified = 0;
        cmp_n = log_compare(lsnp, &LSN(pagep));
        cmp_p = log_compare(&LSN(pagep), &argp->page_lsn);
-       if ((created || cmp_p == 0) && redo) {
+       if (cmp_p == 0 && redo) {
                /* Need to redo update described. */
                P_INIT(pagep, file_dbp->pgsize,
                    argp->pgno, PGNO_INVALID, PGNO_INVALID, 0, argp->ptype);
 
                pagep->lsn = *lsnp;
                modified = 1;
-       } else if ((created || cmp_n == 0) && !redo) {
+       } else if (cmp_n == 0 && !redo) {
                /* Need to undo update described. */
                P_INIT(pagep, file_dbp->pgsize,
                    argp->pgno, PGNO_INVALID, meta->free, 0, P_INVALID);
index 70ab63b..38dbbd1 100644 (file)
@@ -1,14 +1,14 @@
 /*-
  * See the file LICENSE for redistribution information.
  *
- * Copyright (c) 1997
+ * Copyright (c) 1997, 1998
  *     Sleepycat Software.  All rights reserved.
  */
 
 #include "config.h"
 
 #ifndef lint
-static const char sccsid[] = "@(#)bt_recno.c   10.26 (Sleepycat) 1/8/98";
+static const char sccsid[] = "@(#)bt_recno.c   10.37 (Sleepycat) 5/23/98";
 #endif /* not lint */
 
 #ifndef NO_SYSTEM_INCLUDES
@@ -16,8 +16,6 @@ static const char sccsid[] = "@(#)bt_recno.c  10.26 (Sleepycat) 1/8/98";
 
 #include <errno.h>
 #include <limits.h>
-#include <stdio.h>
-#include <stdlib.h>
 #include <string.h>
 #endif
 
@@ -25,16 +23,17 @@ static const char sccsid[] = "@(#)bt_recno.c        10.26 (Sleepycat) 1/8/98";
 #include "db_page.h"
 #include "btree.h"
 
-static int __ram_add __P((DB *, db_recno_t *, DBT *, int, int));
+static int __ram_add __P((DB *, db_recno_t *, DBT *, u_int32_t, u_int32_t));
 static int __ram_c_close __P((DBC *));
-static int __ram_c_del __P((DBC *, int));
-static int __ram_c_get __P((DBC *, DBT *, DBT *, int));
-static int __ram_c_put __P((DBC *, DBT *, DBT *, int));
+static int __ram_c_del __P((DBC *, u_int32_t));
+static int __ram_c_get __P((DBC *, DBT *, DBT *, u_int32_t));
+static int __ram_c_put __P((DBC *, DBT *, DBT *, u_int32_t));
 static int __ram_fmap __P((DB *, db_recno_t));
-static int __ram_get __P((DB *, DB_TXN *, DBT *, DBT *, int));
-static int __ram_put __P((DB *, DB_TXN *, DBT *, DBT *, int));
+static int __ram_get __P((DB *, DB_TXN *, DBT *, DBT *, u_int32_t));
+static int __ram_iget __P((DB *, DBT *, DBT *));
+static int __ram_put __P((DB *, DB_TXN *, DBT *, DBT *, u_int32_t));
 static int __ram_source __P((DB *, RECNO *, const char *));
-static int __ram_sync __P((DB *, int));
+static int __ram_sync __P((DB *, u_int32_t));
 static int __ram_update __P((DB *, db_recno_t, int));
 static int __ram_vmap __P((DB *, db_recno_t));
 static int __ram_writeback __P((DB *));
@@ -142,7 +141,7 @@ __ram_open(dbp, type, dbinfo)
 
 err:   /* If we mmap'd a source file, discard it. */
        if (rp->re_smap != NULL)
-               (void)__db_unmap(rp->re_smap, rp->re_msize);
+               (void)__db_unmapfile(rp->re_smap, rp->re_msize);
 
        /* If we opened a source file, discard it. */
        if (rp->re_fd != -1)
@@ -199,9 +198,9 @@ __ram_cursor(dbp, txn, dbcp)
         * All cursors are queued from the master DB structure.  Add the
         * cursor to that queue.
         */
-       DB_THREAD_LOCK(dbp);
+       CURSOR_SETUP(dbp);
        TAILQ_INSERT_HEAD(&dbp->curs_queue, dbc, links);
-       DB_THREAD_UNLOCK(dbp);
+       CURSOR_TEARDOWN(dbp);
 
        *dbcp = dbc;
        return (0);
@@ -216,16 +215,10 @@ __ram_get(argdbp, txn, key, data, flags)
        DB *argdbp;
        DB_TXN *txn;
        DBT *key, *data;
-       int flags;
+       u_int32_t flags;
 {
-       BTREE *t;
        DB *dbp;
-       PAGE *h;
-       db_indx_t indx;
-       db_recno_t recno;
-       int exact, ret, stack;
-
-       stack = 0;
+       int ret;
 
        DEBUG_LWRITE(argdbp, txn, "ram_get", key, NULL, flags);
 
@@ -234,6 +227,30 @@ __ram_get(argdbp, txn, key, data, flags)
                return (ret);
 
        GETHANDLE(argdbp, txn, &dbp, ret);
+
+       ret = __ram_iget(dbp, key, data);
+
+       PUTHANDLE(dbp);
+       return (ret);
+}
+
+/*
+ * __ram_iget --
+ *     Internal ram get function, called for both standard and cursor
+ *     get after the flags have been checked.
+ */
+static int
+__ram_iget(dbp, key, data)
+       DB *dbp;
+       DBT *key, *data;
+{
+       BTREE *t;
+       PAGE *h;
+       db_indx_t indx;
+       db_recno_t recno;
+       int exact, ret, stack;
+
+       stack = 0;
        t = dbp->internal;
 
        /* Check the user's record number and fill in as necessary. */
@@ -265,7 +282,6 @@ done:       /* Discard the stack. */
        if (stack)
                __bam_stkrel(dbp);
 
-       PUTHANDLE(dbp);
        return (ret);
 }
 
@@ -278,7 +294,7 @@ __ram_put(argdbp, txn, key, data, flags)
        DB *argdbp;
        DB_TXN *txn;
        DBT *key, *data;
-       int flags;
+       u_int32_t flags;
 {
        BTREE *t;
        DB *dbp;
@@ -324,7 +340,7 @@ __ram_put(argdbp, txn, key, data, flags)
 static int
 __ram_sync(argdbp, flags)
        DB *argdbp;
-       int flags;
+       u_int32_t flags;
 {
        DB *dbp;
        int ret;
@@ -361,7 +377,7 @@ __ram_close(argdbp)
 
        /* Close any underlying mmap region. */
        if (rp->re_smap != NULL)
-               (void)__db_unmap(rp->re_smap, rp->re_msize);
+               (void)__db_unmapfile(rp->re_smap, rp->re_msize);
 
        /* Close any backing source file descriptor. */
        if (rp->re_fd != -1)
@@ -403,17 +419,10 @@ __ram_c_iclose(dbp, dbc)
        DB *dbp;
        DBC *dbc;
 {
-       /*
-        * All cursors are queued from the master DB structure.  For
-        * now, discard the DB handle which triggered this call, and
-        * replace it with the cursor's reference.
-        */
-       dbp = dbc->dbp;
-
        /* Remove the cursor from the queue. */
-       DB_THREAD_LOCK(dbp);
+       CURSOR_SETUP(dbp);
        TAILQ_REMOVE(&dbp->curs_queue, dbc, links);
-       DB_THREAD_UNLOCK(dbp);
+       CURSOR_TEARDOWN(dbp);
 
        /* Discard the structures. */
        FREE(dbc->internal, sizeof(RCURSOR));
@@ -429,7 +438,7 @@ __ram_c_iclose(dbp, dbc)
 static int
 __ram_c_del(dbc, flags)
        DBC *dbc;
-       int flags;
+       u_int32_t flags;
 {
        DBT key;
        RCURSOR *cp;
@@ -466,7 +475,7 @@ static int
 __ram_c_get(dbc, key, data, flags)
        DBC *dbc;
        DBT *key, *data;
-       int flags;
+       u_int32_t flags;
 {
        BTREE *t;
        DB *dbp;
@@ -537,7 +546,7 @@ retry:      /* Update the record number. */
 
        /*
         * Return the key if the user didn't give us one, and then pass it
-        * into __ram_get().
+        * into __ram_iget().
         */
        if (flags != DB_SET && flags != DB_SET_RANGE &&
            (ret = __db_retcopy(key, &cp->recno, sizeof(cp->recno),
@@ -555,7 +564,7 @@ retry:      /* Update the record number. */
         *
         * Skip any keys that don't really exist.
         */
-       if ((ret = __ram_get(dbp, dbc->txn, key, data, 0)) != 0)
+       if ((ret = __ram_iget(dbp, key, data)) != 0)
                if (ret == DB_KEYEMPTY &&
                    (flags == DB_NEXT || flags == DB_PREV))
                        goto retry;
@@ -575,7 +584,7 @@ static int
 __ram_c_put(dbc, key, data, flags)
        DBC *dbc;
        DBT *key, *data;
-       int flags;
+       u_int32_t flags;
 {
        BTREE *t;
        RCURSOR *cp, copy;
@@ -624,28 +633,21 @@ split:            arg = &cp->recno;
        if ((ret = __bam_stkrel(dbp)) != 0)
                goto err;
 
-       if (flags != DB_CURRENT) {
-               /* Adjust the counts. */
-               if ((ret = __bam_adjust(dbp, t, 1)) != 0)
-                       goto err;
-
-               switch (flags) {
-               case DB_AFTER:
-                       /* Adjust the cursors. */
-                       __ram_ca(dbp, cp->recno, CA_IAFTER);
-
-                       /* Set this cursor to reference the new record. */
-                       cp->recno = copy.recno + 1;
-                       break;
-               case DB_BEFORE:
-                       /* Adjust the cursors. */
-                       __ram_ca(dbp, cp->recno, CA_IBEFORE);
+       switch (flags) {
+       case DB_AFTER:
+               /* Adjust the cursors. */
+               __ram_ca(dbp, cp->recno, CA_IAFTER);
 
-                       /* Set this cursor to reference the new record. */
-                       cp->recno = copy.recno;
-                       break;
-               }
+               /* Set this cursor to reference the new record. */
+               cp->recno = copy.recno + 1;
+               break;
+       case DB_BEFORE:
+               /* Adjust the cursors. */
+               __ram_ca(dbp, cp->recno, CA_IBEFORE);
 
+               /* Set this cursor to reference the new record. */
+               cp->recno = copy.recno;
+               break;
        }
 
        /*
@@ -679,7 +681,7 @@ __ram_ca(dbp, recno, op)
        /*
         * Adjust the cursors.  See the comment in __bam_ca_delete().
         */
-       DB_THREAD_LOCK(dbp);
+       CURSOR_SETUP(dbp);
        for (dbc = TAILQ_FIRST(&dbp->curs_queue);
            dbc != NULL; dbc = TAILQ_NEXT(dbc, links)) {
                cp = (RCURSOR *)dbc->internal;
@@ -698,7 +700,7 @@ __ram_ca(dbp, recno, op)
                        break;
                }
        }
-       DB_THREAD_UNLOCK(dbp);
+       CURSOR_TEARDOWN(dbp);
 }
 
 #ifdef DEBUG
@@ -715,14 +717,15 @@ __ram_cprint(dbp)
        DBC *dbc;
        RCURSOR *cp;
 
-       DB_THREAD_LOCK(dbp);
+       CURSOR_SETUP(dbp);
        for (dbc = TAILQ_FIRST(&dbp->curs_queue);
            dbc != NULL; dbc = TAILQ_NEXT(dbc, links)) {
                cp = (RCURSOR *)dbc->internal;
                fprintf(stderr,
                    "%#0x: recno: %lu\n", (u_int)cp, (u_long)cp->recno);
        }
-       DB_THREAD_UNLOCK(dbp);
+       CURSOR_TEARDOWN(dbp);
+
        return (0);
 }
 #endif /* DEBUG */
@@ -853,11 +856,11 @@ __ram_source(dbp, rp, fname)
        const char *fname;
 {
        size_t size;
-       u_int32_t mbytes, bytes;
-       int oflags, ret;
+       u_int32_t bytes, mbytes, oflags;
+       int ret;
 
        if ((ret = __db_appname(dbp->dbenv,
-           DB_APP_DATA, NULL, fname, NULL, &rp->re_source)) != 0)
+           DB_APP_DATA, NULL, fname, 0, NULL, &rp->re_source)) != 0)
                return (ret);
 
        oflags = F_ISSET(dbp, DB_AM_RDONLY) ? DB_RDONLY : 0;
@@ -886,7 +889,8 @@ __ram_source(dbp, rp, fname)
        }
 
        size = mbytes * MEGABYTE + bytes;
-       if ((ret = __db_map(rp->re_fd, (size_t)size, 1, 1, &rp->re_smap)) != 0)
+       if ((ret = __db_mapfile(rp->re_source,
+           rp->re_fd, (size_t)size, 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);
@@ -952,7 +956,7 @@ __ram_writeback(dbp)
         * open will fail.
         */
        if (rp->re_smap != NULL) {
-               (void)__db_unmap(rp->re_smap, rp->re_msize);
+               (void)__db_unmapfile(rp->re_smap, rp->re_msize);
                rp->re_smap = NULL;
        }
 
@@ -1078,19 +1082,22 @@ __ram_fmap(dbp, top)
 
        sp = (u_int8_t *)rp->re_cmap;
        ep = (u_int8_t *)rp->re_emap;
-       while (recno <= top) {
+       while (recno < top) {
                if (sp >= ep) {
                        F_SET(rp, RECNO_EOF);
                        return (DB_NOTFOUND);
                }
                len = rp->re_len;
                for (p = t->bt_rdata.data;
-                   sp < ep && len > 0; *p++ = *sp++, --len);
+                   sp < ep && len > 0; *p++ = *sp++, --len)
+                       ;
 
                /*
-                * Another process may have read some portion of the input
-                * file already, in which case we just want to discard the
-                * new record.
+                * Another process may have read this record from the input
+                * file and stored it into the database already, in which
+                * case we don't need to repeat that operation.  We detect
+                * this by checking if the last record we've read is greater
+                * or equal to the number of records in the database.
                 *
                 * XXX
                 * We should just do a seek, since the records are fixed
@@ -1138,17 +1145,20 @@ __ram_vmap(dbp, top)
 
        sp = (u_int8_t *)rp->re_cmap;
        ep = (u_int8_t *)rp->re_emap;
-       while (recno <= top) {
+       while (recno < top) {
                if (sp >= ep) {
                        F_SET(rp, RECNO_EOF);
                        return (DB_NOTFOUND);
                }
-               for (data.data = sp; sp < ep && *sp != delim; ++sp);
+               for (data.data = sp; sp < ep && *sp != delim; ++sp)
+                       ;
 
                /*
-                * Another process may have read some portion of the input
-                * file already, in which case we just want to discard the
-                * new record.
+                * Another process may have read this record from the input
+                * file and stored it into the database already, in which
+                * case we don't need to repeat that operation.  We detect
+                * this by checking if the last record we've read is greater
+                * or equal to the number of records in the database.
                 */
                if (rp->re_last >= recno) {
                        data.size = sp - (u_int8_t *)data.data;
@@ -1172,12 +1182,13 @@ __ram_add(dbp, recnop, data, flags, bi_flags)
        DB *dbp;
        db_recno_t *recnop;
        DBT *data;
-       int flags, bi_flags;
+       u_int32_t flags, bi_flags;
 {
+       BKEYDATA *bk;
        BTREE *t;
        PAGE *h;
        db_indx_t indx;
-       int exact, ret, stack;
+       int exact, isdeleted, ret, stack;
 
        t = dbp->internal;
 
@@ -1190,34 +1201,63 @@ retry:  /* Find the slot for insertion. */
        stack = 1;
 
        /*
-        * The recno access method doesn't currently support duplicates, so
-        * if an identical key is already in the tree we're either overwriting
-        * it or an error is returned.
+        * If DB_NOOVERWRITE is set and the item already exists in the tree,
+        * return an error unless the item has been marked for deletion.
         */
-       if (exact && LF_ISSET(DB_NOOVERWRITE)) {
-               ret = DB_KEYEXIST;
-               goto err;
+       isdeleted = 0;
+       if (exact) {
+               bk = GET_BKEYDATA(h, indx);
+               if (B_DISSET(bk->type)) {
+                       isdeleted = 1;
+                       __bam_ca_replace(dbp, h->pgno, indx, REPLACE_SETUP);
+               } else
+                       if (LF_ISSET(DB_NOOVERWRITE)) {
+                               ret = DB_KEYEXIST;
+                               goto err;
+                       }
        }
 
        /*
         * Select the arguments for __bam_iitem() and do the insert.  If the
         * key is an exact match, or we're replacing the data item with a
-        * new data item.  If the key isn't an exact match, we're inserting
-        * a new key/data pair, before the search location.
+        * new data item, replace the current item.  If the key isn't an exact
+        * match, we're inserting a new key/data pair, before the search
+        * location.
         */
-       if ((ret = __bam_iitem(dbp, &h, &indx, NULL,
-           data, exact ? DB_CURRENT : DB_BEFORE, bi_flags)) == DB_NEEDSPLIT) {
+       switch (ret = __bam_iitem(dbp,
+           &h, &indx, NULL, data, exact ? DB_CURRENT : DB_BEFORE, bi_flags)) {
+       case 0:
+               /*
+                * Done.  Clean up the cursor and adjust the internal page
+                * counts.
+                */
+               if (isdeleted)
+                       __bam_ca_replace(dbp, h->pgno, indx, REPLACE_SUCCESS);
+               break;
+       case DB_NEEDSPLIT:
+               /*
+                * We have to split the page.  Back out the cursor setup,
+                * discard the stack of pages, and do the split.
+                */
+               if (isdeleted)
+                       __bam_ca_replace(dbp, h->pgno, indx, REPLACE_FAILED);
+
                (void)__bam_stkrel(dbp);
                stack = 0;
+
                if ((ret = __bam_split(dbp, recnop)) != 0)
-                       goto err;
+                       break;
+
                goto retry;
+               /* NOTREACHED */
+       default:
+               if (isdeleted)
+                       __bam_ca_replace(dbp, h->pgno, indx, REPLACE_FAILED);
+               break;
        }
 
-       if (!exact && ret == 0)
-               __bam_adjust(dbp, t, 1);
-
 err:   if (stack)
                __bam_stkrel(dbp);
+
        return (ret);
 }
index ee26221..caa6b35 100644 (file)
@@ -1,7 +1,7 @@
 /*-
  * See the file LICENSE for redistribution information.
  *
- * Copyright (c) 1996, 1997
+ * Copyright (c) 1996, 1997, 1998
  *     Sleepycat Software.  All rights reserved.
  */
 /*
 #include "config.h"
 
 #ifndef lint
-static const char sccsid[] = "@(#)bt_rsearch.c 10.8 (Sleepycat) 8/24/97";
+static const char sccsid[] = "@(#)bt_rsearch.c 10.15 (Sleepycat) 5/6/98";
 #endif /* not lint */
 
 #ifndef NO_SYSTEM_INCLUDES
 #include <sys/types.h>
-
-#include <stdio.h>
-#include <stdlib.h>
 #endif
 
 #include "db_int.h"
@@ -62,13 +59,13 @@ static const char sccsid[] = "@(#)bt_rsearch.c      10.8 (Sleepycat) 8/24/97";
  * __bam_rsearch --
  *     Search a btree for a record number.
  *
- * PUBLIC: int __bam_rsearch __P((DB *, db_recno_t *, u_int, int, int *));
+ * PUBLIC: int __bam_rsearch __P((DB *, db_recno_t *, u_int32_t, int, int *));
  */
 int
 __bam_rsearch(dbp, recnop, flags, stop, exactp)
        DB *dbp;
        db_recno_t *recnop;
-       u_int flags;
+       u_int32_t flags;
        int stop, *exactp;
 {
        BINTERNAL *bi;
@@ -78,7 +75,7 @@ __bam_rsearch(dbp, recnop, flags, stop, exactp)
        RINTERNAL *ri;
        db_indx_t indx, top;
        db_pgno_t pg;
-       db_recno_t recno, total;
+       db_recno_t i, recno, total;
        int isappend, ret, stack;
 
        t = dbp->internal;
@@ -136,8 +133,7 @@ __bam_rsearch(dbp, recnop, flags, stop, exactp)
                        *exactp = 1;
                else {
                        *exactp = 0;
-                       if (flags == S_DELETE ||
-                           flags == S_FIND || recno > total + 1) {
+                       if (!PAST_END_OK(flags) || recno > total + 1) {
                                (void)memp_fput(dbp->mpf, h, 0);
                                (void)__BT_LPUT(dbp, lock);
                                return (DB_NOTFOUND);
@@ -164,30 +160,65 @@ __bam_rsearch(dbp, recnop, flags, stop, exactp)
                stack = 1;
        }
 
-       /* Records in the tree are 0-based, and record numbers are 1-based. */
-       --recno;
-
+       /*
+        * !!!
+        * Record numbers in the tree are 0-based, but the recno is
+        * 1-based.  All of the calculations below have to take this
+        * into account.
+        */
        for (total = 0;;) {
                switch (TYPE(h)) {
                case P_LBTREE:
-                       BT_STK_ENTER(t, h, (recno - total) * P_INDX, lock, ret);
+                       recno -= total;
+
+                       /*
+                        * There may be logically deleted records on the page,
+                        * walk the page correcting for them.  The record may
+                        * not exist if there are enough deleted records in the
+                        * page.
+                        */
+                       if (recno <= NUM_ENT(h))
+                               for (i = recno - 1;; --i) {
+                                       if (B_DISSET(GET_BKEYDATA(h,
+                                           i * P_INDX + O_INDX)->type))
+                                               ++recno;
+                                       if (i == 0)
+                                               break;
+                               }
+                       if (recno > NUM_ENT(h)) {
+                               *exactp = 0;
+                               if (!PAST_END_OK(flags) ||
+                                   recno > (db_recno_t)(NUM_ENT(h) + 1)) {
+                                       ret = DB_NOTFOUND;
+                                       goto err;
+                               }
+
+                       }
+
+                       /* Correct from 1-based to 0-based for a page offset. */
+                       --recno;
+                       BT_STK_ENTER(t, h, recno * P_INDX, lock, ret);
                        return (ret);
                case P_IBTREE:
                        for (indx = 0, top = NUM_ENT(h);;) {
                                bi = GET_BINTERNAL(h, indx);
-                               if (++indx == top || total + bi->nrecs > recno)
+                               if (++indx == top || total + bi->nrecs >= recno)
                                        break;
                                total += bi->nrecs;
                        }
                        pg = bi->pgno;
                        break;
                case P_LRECNO:
-                       BT_STK_ENTER(t, h, recno - total, lock, ret);
+                       recno -= total;
+
+                       /* Correct from 1-based to 0-based for a page offset. */
+                       --recno;
+                       BT_STK_ENTER(t, h, recno, lock, ret);
                        return (ret);
                case P_IRECNO:
                        for (indx = 0, top = NUM_ENT(h);;) {
                                ri = GET_RINTERNAL(h, indx);
-                               if (++indx == top || total + ri->nrecs > recno)
+                               if (++indx == top || total + ri->nrecs >= recno)
                                        break;
                                total += ri->nrecs;
                        }
@@ -244,13 +275,13 @@ err:      BT_STK_POP(t);
  * __bam_adjust --
  *     Adjust the tree after adding or deleting a record.
  *
- * PUBLIC: int __bam_adjust __P((DB *, BTREE *, int));
+ * PUBLIC: int __bam_adjust __P((DB *, BTREE *, int32_t));
  */
 int
 __bam_adjust(dbp, t, adjust)
        DB *dbp;
        BTREE *t;
-       int adjust;
+       int32_t adjust;
 {
        EPG *epg;
        PAGE *h;
@@ -264,7 +295,7 @@ __bam_adjust(dbp, t, adjust)
                            (ret = __bam_cadjust_log(dbp->dbenv->lg_info,
                            dbp->txn, &LSN(h), 0, dbp->log_fileid,
                            PGNO(h), &LSN(h), (u_int32_t)epg->indx,
-                           (int32_t)adjust, 1)) != 0)
+                           adjust, 1)) != 0)
                                return (ret);
 
                        if (TYPE(h) == P_IBTREE)
@@ -322,26 +353,31 @@ db_recno_t
 __bam_total(h)
        PAGE *h;
 {
-       db_recno_t recs;
-       db_indx_t nxt, top;
+       db_recno_t nrecs;
+       db_indx_t indx, top;
+
+       nrecs = 0;
+       top = NUM_ENT(h);
 
        switch (TYPE(h)) {
        case P_LBTREE:
-               recs = NUM_ENT(h) / 2;
+               /* Check for logically deleted records. */
+               for (indx = 0; indx < top; indx += P_INDX)
+                       if (!B_DISSET(GET_BKEYDATA(h, indx + O_INDX)->type))
+                               ++nrecs;
                break;
        case P_IBTREE:
-               for (recs = 0, nxt = 0, top = NUM_ENT(h); nxt < top; ++nxt)
-                       recs += GET_BINTERNAL(h, nxt)->nrecs;
+               for (indx = 0; indx < top; indx += O_INDX)
+                       nrecs += GET_BINTERNAL(h, indx)->nrecs;
                break;
        case P_LRECNO:
-               recs = NUM_ENT(h);
+               nrecs = NUM_ENT(h);
                break;
        case P_IRECNO:
-               for (recs = 0, nxt = 0, top = NUM_ENT(h); nxt < top; ++nxt)
-                       recs += GET_RINTERNAL(h, nxt)->nrecs;
+               for (indx = 0; indx < top; indx += O_INDX)
+                       nrecs += GET_RINTERNAL(h, indx)->nrecs;
                break;
-       default:
-               abort();
        }
-       return (recs);
+
+       return (nrecs);
 }
index c39c9af..09ce46d 100644 (file)
@@ -1,7 +1,7 @@
 /*-
  * See the file LICENSE for redistribution information.
  *
- * Copyright (c) 1996, 1997
+ * Copyright (c) 1996, 1997, 1998
  *     Sleepycat Software.  All rights reserved.
  */
 /*
 #include "config.h"
 
 #ifndef lint
-static const char sccsid[] = "@(#)bt_search.c  10.9 (Sleepycat) 11/18/97";
+static const char sccsid[] = "@(#)bt_search.c  10.15 (Sleepycat) 5/6/98";
 #endif /* not lint */
 
 #ifndef NO_SYSTEM_INCLUDES
 #include <sys/types.h>
 
 #include <errno.h>
-#include <stdio.h>
-#include <stdlib.h>
 #include <string.h>
 #endif
 
@@ -68,13 +66,13 @@ static const char sccsid[] = "@(#)bt_search.c       10.9 (Sleepycat) 11/18/97";
  *     Search a btree for a key.
  *
  * PUBLIC: int __bam_search __P((DB *,
- * PUBLIC:     const DBT *, u_int, int, db_recno_t *, int *));
+ * PUBLIC:     const DBT *, u_int32_t, int, db_recno_t *, int *));
  */
 int
 __bam_search(dbp, key, flags, stop, recnop, exactp)
        DB *dbp;
        const DBT *key;
-       u_int flags;
+       u_int32_t flags;
        int stop, *exactp;
        db_recno_t *recnop;
 {
@@ -109,8 +107,7 @@ __bam_search(dbp, key, flags, stop, recnop, exactp)
         * Retrieve the root page.
         */
        pg = PGNO_ROOT;
-       stack = F_ISSET(dbp, DB_BT_RECNUM) &&
-           (flags == S_INSERT || flags == S_DELETE);
+       stack = F_ISSET(dbp, DB_BT_RECNUM) && LF_ISSET(S_STACK);
        if ((ret = __bam_lget(dbp,
            0, pg, stack ? DB_LOCK_WRITE : DB_LOCK_READ, &lock)) != 0)
                return (ret);
@@ -179,6 +176,14 @@ __bam_search(dbp, key, flags, stop, recnop, exactp)
                        if (LF_ISSET(S_EXACT))
                                goto notfound;
 
+                       /*
+                        * !!!
+                        * Possibly returning a deleted record -- DB_SET_RANGE,
+                        * DB_KEYFIRST and DB_KEYLAST don't require an exact
+                        * match, and we don't want to walk multiple pages here
+                        * to find an undeleted record.  This is handled in the
+                        * __bam_c_search() routine.
+                        */
                        BT_STK_ENTER(t, h, base, lock, ret);
                        return (ret);
                }
@@ -249,7 +254,10 @@ match:     *exactp = 1;
        /*
         * If we got here, we know that we have a btree leaf page.
         *
-        * If there are duplicates, go to the first/last one.
+        * If there are duplicates, go to the first/last one.  This is
+        * safe because we know that we're not going to leave the page,
+        * all duplicate sets that are not on overflow pages exist on a
+        * single leaf page.
         */
        if (LF_ISSET(S_DUPLAST))
                while (indx < (db_indx_t)(NUM_ENT(h) - P_INDX) &&
@@ -261,8 +269,8 @@ match:      *exactp = 1;
                        indx -= P_INDX;
 
        /*
-        * Now check if we are allowed to return deleted item; if not
-        * find/last the first non-deleted item.
+        * Now check if we are allowed to return deleted items; if not
+        * find the next (or previous) non-deleted item.
         */
        if (LF_ISSET(S_DELNO)) {
                if (LF_ISSET(S_DUPLAST))
index 219d486..da9417c 100644 (file)
@@ -1,7 +1,7 @@
 /*-
  * See the file LICENSE for redistribution information.
  *
- * Copyright (c) 1996, 1997
+ * Copyright (c) 1996, 1997, 1998
  *     Sleepycat Software.  All rights reserved.
  */
 /*
@@ -44,7 +44,7 @@
 #include "config.h"
 
 #ifndef lint
-static const char sccsid[] = "@(#)bt_split.c   10.18 (Sleepycat) 11/23/97";
+static const char sccsid[] = "@(#)bt_split.c   10.23 (Sleepycat) 5/23/98";
 #endif /* not lint */
 
 #ifndef NO_SYSTEM_INCLUDES
@@ -52,8 +52,6 @@ static const char sccsid[] = "@(#)bt_split.c  10.18 (Sleepycat) 11/23/97";
 
 #include <errno.h>
 #include <limits.h>
-#include <stdio.h>
-#include <stdlib.h>
 #include <string.h>
 #endif
 
@@ -168,8 +166,10 @@ __bam_root(dbp, cp)
        t = dbp->internal;
 
        /* Yeah, right. */
-       if (cp->page->level >= MAXBTREELEVEL)
-               return (ENOSPC);
+       if (cp->page->level >= MAXBTREELEVEL) {
+               ret = ENOSPC;
+               goto err;
+       }
 
        /* Create new left and right pages for the split. */
        lp = rp = NULL;
@@ -237,18 +237,16 @@ __bam_page(dbp, pp, cp)
        DB *dbp;
        EPG *pp, *cp;
 {
-       BTREE *t;
        DB_LOCK tplock;
        PAGE *lp, *rp, *tp;
        int ret;
 
-       t = dbp->internal;
        lp = rp = tp = NULL;
        ret = -1;
 
        /* Create new right page for the split. */
        if ((ret = __bam_new(dbp, TYPE(cp->page), &rp)) != 0)
-               return (ret);
+               goto err;
        P_INIT(rp, dbp->pgsize, rp->pgno,
            ISINTERNAL(cp->page) ? PGNO_INVALID : cp->page->pgno,
            ISINTERNAL(cp->page) ? PGNO_INVALID : cp->page->next_pgno,
@@ -259,7 +257,7 @@ __bam_page(dbp, pp, cp)
                ret = ENOMEM;
                goto err;
        }
-#ifdef DEBUG
+#ifdef DIAGNOSTIC
        memset(lp, 0xff, dbp->pgsize);
 #endif
        P_INIT(lp, dbp->pgsize, cp->page->pgno,
@@ -906,13 +904,13 @@ __bam_copy(dbp, pp, cp, nxt, stop)
        PAGE *pp, *cp;
        u_int32_t nxt, stop;
 {
-       db_indx_t dup, nbytes, off;
+       db_indx_t nbytes, off;
 
        /*
         * Copy the rest of the data to the right page.  Nxt is the next
         * offset placed on the target page.
         */
-       for (dup = off = 0; nxt < stop; ++nxt, ++NUM_ENT(cp), ++off) {
+       for (off = 0; nxt < stop; ++nxt, ++NUM_ENT(cp), ++off) {
                switch (TYPE(pp)) {
                case P_IBTREE:
                        if (B_TYPE(GET_BINTERNAL(pp, nxt)->type) == B_KEYDATA)
index e88b5da..2236434 100644 (file)
@@ -1,21 +1,20 @@
 /*-
  * See the file LICENSE for redistribution information.
  *
- * Copyright (c) 1996, 1997
+ * Copyright (c) 1996, 1997, 1998
  *     Sleepycat Software.  All rights reserved.
  */
 
 #include "config.h"
 
 #ifndef lint
-static const char sccsid[] = "@(#)bt_stat.c    10.14 (Sleepycat) 10/25/97";
+static const char sccsid[] = "@(#)bt_stat.c    10.17 (Sleepycat) 4/26/98";
 #endif /* not lint */
 
 #ifndef NO_SYSTEM_INCLUDES
 #include <sys/types.h>
 
 #include <errno.h>
-#include <stdlib.h>
 #include <string.h>
 #endif
 
@@ -29,14 +28,14 @@ static void __bam_add_rstat __P((DB_BTREE_LSTAT *, DB_BTREE_STAT *));
  * __bam_stat --
  *     Gather/print the btree statistics
  *
- * PUBLIC: int __bam_stat __P((DB *, void *, void *(*)(size_t), int));
+ * PUBLIC: int __bam_stat __P((DB *, void *, void *(*)(size_t), u_int32_t));
  */
 int
 __bam_stat(argdbp, spp, db_malloc, flags)
        DB *argdbp;
        void *spp;
        void *(*db_malloc) __P((size_t));
-       int flags;
+       u_int32_t flags;
 {
        BTMETA *meta;
        BTREE *t;
index 6145696..928dce2 100644 (file)
@@ -1,16 +1,12 @@
 /*-
  * See the file LICENSE for redistribution information.
  *
- * Copyright (c) 1996, 1997
+ * Copyright (c) 1996, 1997, 1998
  *     Sleepycat Software.  All rights reserved.
+ *
+ *     @(#)btree.src   10.8 (Sleepycat) 4/10/98
  */
 
-#include "config.h"
-
-#ifndef lint
-static const char sccsid[] = "@(#)btree.src    10.6 (Sleepycat) 11/2/97";
-#endif /* not lint */
-
 PREFIX bam
 
 /*
index 18bbd5d..75eadb1 100644 (file)
@@ -15,8 +15,6 @@
 #include "db_dispatch.h"
 #include "btree.h"
 #include "db_am.h"
-#include "common_ext.h"
-
 /*
  * PUBLIC: int __bam_pg_alloc_log
  * PUBLIC:     __P((DB_LOG *, DB_TXN *, DB_LSN *, u_int32_t,
@@ -85,7 +83,7 @@ int __bam_pg_alloc_log(logp, txnid, ret_lsnp, flags,
        bp += sizeof(ptype);
        memcpy(bp, &next, sizeof(next));
        bp += sizeof(next);
-#ifdef DEBUG
+#ifdef DIAGNOSTIC
        if ((u_int32_t)(bp - (u_int8_t *)logrec.data) != logrec.size)
                fprintf(stderr, "Error in log record length");
 #endif
@@ -101,22 +99,23 @@ int __bam_pg_alloc_log(logp, txnid, ret_lsnp, flags,
  * PUBLIC:    __P((DB_LOG *, DBT *, DB_LSN *, int, void *));
  */
 int
-__bam_pg_alloc_print(notused1, dbtp, lsnp, notused3, notused4)
+__bam_pg_alloc_print(notused1, dbtp, lsnp, notused2, notused3)
        DB_LOG *notused1;
        DBT *dbtp;
        DB_LSN *lsnp;
-       int notused3;
-       void *notused4;
+       int notused2;
+       void *notused3;
 {
        __bam_pg_alloc_args *argp;
        u_int32_t i;
-       int c, ret;
+       u_int ch;
+       int ret;
 
        i = 0;
-       c = 0;
+       ch = 0;
        notused1 = NULL;
-       notused3 = 0;
-       notused4 = NULL;
+       notused2 = 0;
+       notused3 = NULL;
 
        if ((ret = __bam_pg_alloc_read(dbtp->data, &argp)) != 0)
                return (ret);
@@ -249,7 +248,7 @@ int __bam_pg_free_log(logp, txnid, ret_lsnp, flags,
        }
        memcpy(bp, &next, sizeof(next));
        bp += sizeof(next);
-#ifdef DEBUG
+#ifdef DIAGNOSTIC
        if ((u_int32_t)(bp - (u_int8_t *)logrec.data) != logrec.size)
                fprintf(stderr, "Error in log record length");
 #endif
@@ -265,22 +264,23 @@ int __bam_pg_free_log(logp, txnid, ret_lsnp, flags,
  * PUBLIC:    __P((DB_LOG *, DBT *, DB_LSN *, int, void *));
  */
 int
-__bam_pg_free_print(notused1, dbtp, lsnp, notused3, notused4)
+__bam_pg_free_print(notused1, dbtp, lsnp, notused2, notused3)
        DB_LOG *notused1;
        DBT *dbtp;
        DB_LSN *lsnp;
-       int notused3;
-       void *notused4;
+       int notused2;
+       void *notused3;
 {
        __bam_pg_free_args *argp;
        u_int32_t i;
-       int c, ret;
+       u_int ch;
+       int ret;
 
        i = 0;
-       c = 0;
+       ch = 0;
        notused1 = NULL;
-       notused3 = 0;
-       notused4 = NULL;
+       notused2 = 0;
+       notused3 = NULL;
 
        if ((ret = __bam_pg_free_read(dbtp->data, &argp)) != 0)
                return (ret);
@@ -297,11 +297,11 @@ __bam_pg_free_print(notused1, dbtp, lsnp, notused3, notused4)
            (u_long)argp->meta_lsn.file, (u_long)argp->meta_lsn.offset);
        printf("\theader: ");
        for (i = 0; i < argp->header.size; i++) {
-               c = ((char *)argp->header.data)[i];
-               if (isprint(c) || c == 0xa)
-                       putchar(c);
+               ch = ((u_int8_t *)argp->header.data)[i];
+               if (isprint(ch) || ch == 0xa)
+                       putchar(ch);
                else
-                       printf("%#x ", c);
+                       printf("%#x ", ch);
        }
        printf("\n");
        printf("\tnext: %lu\n", (u_long)argp->next);
@@ -443,7 +443,7 @@ int __bam_split_log(logp, txnid, ret_lsnp, flags,
                memcpy(bp, pg->data, pg->size);
                bp += pg->size;
        }
-#ifdef DEBUG
+#ifdef DIAGNOSTIC
        if ((u_int32_t)(bp - (u_int8_t *)logrec.data) != logrec.size)
                fprintf(stderr, "Error in log record length");
 #endif
@@ -459,22 +459,23 @@ int __bam_split_log(logp, txnid, ret_lsnp, flags,
  * PUBLIC:    __P((DB_LOG *, DBT *, DB_LSN *, int, void *));
  */
 int
-__bam_split_print(notused1, dbtp, lsnp, notused3, notused4)
+__bam_split_print(notused1, dbtp, lsnp, notused2, notused3)
        DB_LOG *notused1;
        DBT *dbtp;
        DB_LSN *lsnp;
-       int notused3;
-       void *notused4;
+       int notused2;
+       void *notused3;
 {
        __bam_split_args *argp;
        u_int32_t i;
-       int c, ret;
+       u_int ch;
+       int ret;
 
        i = 0;
-       c = 0;
+       ch = 0;
        notused1 = NULL;
-       notused3 = 0;
-       notused4 = NULL;
+       notused2 = 0;
+       notused3 = NULL;
 
        if ((ret = __bam_split_read(dbtp->data, &argp)) != 0)
                return (ret);
@@ -498,11 +499,11 @@ __bam_split_print(notused1, dbtp, lsnp, notused3, notused4)
            (u_long)argp->nlsn.file, (u_long)argp->nlsn.offset);
        printf("\tpg: ");
        for (i = 0; i < argp->pg.size; i++) {
-               c = ((char *)argp->pg.data)[i];
-               if (isprint(c) || c == 0xa)
-                       putchar(c);
+               ch = ((u_int8_t *)argp->pg.data)[i];
+               if (isprint(ch) || ch == 0xa)
+                       putchar(ch);
                else
-                       printf("%#x ", c);
+                       printf("%#x ", ch);
        }
        printf("\n");
        printf("\n");
@@ -639,7 +640,7 @@ int __bam_rsplit_log(logp, txnid, ret_lsnp, flags,
        else
                memset(bp, 0, sizeof(*rootlsn));
        bp += sizeof(*rootlsn);
-#ifdef DEBUG
+#ifdef DIAGNOSTIC
        if ((u_int32_t)(bp - (u_int8_t *)logrec.data) != logrec.size)
                fprintf(stderr, "Error in log record length");
 #endif
@@ -655,22 +656,23 @@ int __bam_rsplit_log(logp, txnid, ret_lsnp, flags,
  * PUBLIC:    __P((DB_LOG *, DBT *, DB_LSN *, int, void *));
  */
 int
-__bam_rsplit_print(notused1, dbtp, lsnp, notused3, notused4)
+__bam_rsplit_print(notused1, dbtp, lsnp, notused2, notused3)
        DB_LOG *notused1;
        DBT *dbtp;
        DB_LSN *lsnp;
-       int notused3;
-       void *notused4;
+       int notused2;
+       void *notused3;
 {
        __bam_rsplit_args *argp;
        u_int32_t i;
-       int c, ret;
+       u_int ch;
+       int ret;
 
        i = 0;
-       c = 0;
+       ch = 0;
        notused1 = NULL;
-       notused3 = 0;
-       notused4 = NULL;
+       notused2 = 0;
+       notused3 = NULL;
 
        if ((ret = __bam_rsplit_read(dbtp->data, &argp)) != 0)
                return (ret);
@@ -685,21 +687,21 @@ __bam_rsplit_print(notused1, dbtp, lsnp, notused3, notused4)
        printf("\tpgno: %lu\n", (u_long)argp->pgno);
        printf("\tpgdbt: ");
        for (i = 0; i < argp->pgdbt.size; i++) {
-               c = ((char *)argp->pgdbt.data)[i];
-               if (isprint(c) || c == 0xa)
-                       putchar(c);
+               ch = ((u_int8_t *)argp->pgdbt.data)[i];
+               if (isprint(ch) || ch == 0xa)
+                       putchar(ch);
                else
-                       printf("%#x ", c);
+                       printf("%#x ", ch);
        }
        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];
-               if (isprint(c) || c == 0xa)
-                       putchar(c);
+               ch = ((u_int8_t *)argp->rootent.data)[i];
+               if (isprint(ch) || ch == 0xa)
+                       putchar(ch);
                else
-                       printf("%#x ", c);
+                       printf("%#x ", ch);
        }
        printf("\n");
        printf("\trootlsn: [%lu][%lu]\n",
@@ -817,7 +819,7 @@ int __bam_adj_log(logp, txnid, ret_lsnp, flags,
        bp += sizeof(indx_copy);
        memcpy(bp, &is_insert, sizeof(is_insert));
        bp += sizeof(is_insert);
-#ifdef DEBUG
+#ifdef DIAGNOSTIC
        if ((u_int32_t)(bp - (u_int8_t *)logrec.data) != logrec.size)
                fprintf(stderr, "Error in log record length");
 #endif
@@ -833,22 +835,23 @@ int __bam_adj_log(logp, txnid, ret_lsnp, flags,
  * PUBLIC:    __P((DB_LOG *, DBT *, DB_LSN *, int, void *));
  */
 int
-__bam_adj_print(notused1, dbtp, lsnp, notused3, notused4)
+__bam_adj_print(notused1, dbtp, lsnp, notused2, notused3)
        DB_LOG *notused1;
        DBT *dbtp;
        DB_LSN *lsnp;
-       int notused3;
-       void *notused4;
+       int notused2;
+       void *notused3;
 {
        __bam_adj_args *argp;
        u_int32_t i;
-       int c, ret;
+       u_int ch;
+       int ret;
 
        i = 0;
-       c = 0;
+       ch = 0;
        notused1 = NULL;
-       notused3 = 0;
-       notused4 = NULL;
+       notused2 = 0;
+       notused3 = NULL;
 
        if ((ret = __bam_adj_read(dbtp->data, &argp)) != 0)
                return (ret);
@@ -975,7 +978,7 @@ int __bam_cadjust_log(logp, txnid, ret_lsnp, flags,
        bp += sizeof(adjust);
        memcpy(bp, &total, sizeof(total));
        bp += sizeof(total);
-#ifdef DEBUG
+#ifdef DIAGNOSTIC
        if ((u_int32_t)(bp - (u_int8_t *)logrec.data) != logrec.size)
                fprintf(stderr, "Error in log record length");
 #endif
@@ -991,22 +994,23 @@ int __bam_cadjust_log(logp, txnid, ret_lsnp, flags,
  * PUBLIC:    __P((DB_LOG *, DBT *, DB_LSN *, int, void *));
  */
 int
-__bam_cadjust_print(notused1, dbtp, lsnp, notused3, notused4)
+__bam_cadjust_print(notused1, dbtp, lsnp, notused2, notused3)
        DB_LOG *notused1;
        DBT *dbtp;
        DB_LSN *lsnp;
-       int notused3;
-       void *notused4;
+       int notused2;
+       void *notused3;
 {
        __bam_cadjust_args *argp;
        u_int32_t i;
-       int c, ret;
+       u_int ch;
+       int ret;
 
        i = 0;
-       c = 0;
+       ch = 0;
        notused1 = NULL;
-       notused3 = 0;
-       notused4 = NULL;
+       notused2 = 0;
+       notused3 = NULL;
 
        if ((ret = __bam_cadjust_read(dbtp->data, &argp)) != 0)
                return (ret);
@@ -1124,7 +1128,7 @@ int __bam_cdel_log(logp, txnid, ret_lsnp, flags,
        bp += sizeof(*lsn);
        memcpy(bp, &indx, sizeof(indx));
        bp += sizeof(indx);
-#ifdef DEBUG
+#ifdef DIAGNOSTIC
        if ((u_int32_t)(bp - (u_int8_t *)logrec.data) != logrec.size)
                fprintf(stderr, "Error in log record length");
 #endif
@@ -1140,22 +1144,23 @@ int __bam_cdel_log(logp, txnid, ret_lsnp, flags,
  * PUBLIC:    __P((DB_LOG *, DBT *, DB_LSN *, int, void *));
  */
 int
-__bam_cdel_print(notused1, dbtp, lsnp, notused3, notused4)
+__bam_cdel_print(notused1, dbtp, lsnp, notused2, notused3)
        DB_LOG *notused1;
        DBT *dbtp;
        DB_LSN *lsnp;
-       int notused3;
-       void *notused4;
+       int notused2;
+       void *notused3;
 {
        __bam_cdel_args *argp;
        u_int32_t i;
-       int c, ret;
+       u_int ch;
+       int ret;
 
        i = 0;
-       c = 0;
+       ch = 0;
        notused1 = NULL;
-       notused3 = 0;
-       notused4 = NULL;
+       notused2 = 0;
+       notused3 = NULL;
 
        if ((ret = __bam_cdel_read(dbtp->data, &argp)) != 0)
                return (ret);
@@ -1307,7 +1312,7 @@ int __bam_repl_log(logp, txnid, ret_lsnp, flags,
        bp += sizeof(prefix);
        memcpy(bp, &suffix, sizeof(suffix));
        bp += sizeof(suffix);
-#ifdef DEBUG
+#ifdef DIAGNOSTIC
        if ((u_int32_t)(bp - (u_int8_t *)logrec.data) != logrec.size)
                fprintf(stderr, "Error in log record length");
 #endif
@@ -1323,22 +1328,23 @@ int __bam_repl_log(logp, txnid, ret_lsnp, flags,
  * PUBLIC:    __P((DB_LOG *, DBT *, DB_LSN *, int, void *));
  */
 int
-__bam_repl_print(notused1, dbtp, lsnp, notused3, notused4)
+__bam_repl_print(notused1, dbtp, lsnp, notused2, notused3)
        DB_LOG *notused1;
        DBT *dbtp;
        DB_LSN *lsnp;
-       int notused3;
-       void *notused4;
+       int notused2;
+       void *notused3;
 {
        __bam_repl_args *argp;
        u_int32_t i;
-       int c, ret;
+       u_int ch;
+       int ret;
 
        i = 0;
-       c = 0;
+       ch = 0;
        notused1 = NULL;
-       notused3 = 0;
-       notused4 = NULL;
+       notused2 = 0;
+       notused3 = NULL;
 
        if ((ret = __bam_repl_read(dbtp->data, &argp)) != 0)
                return (ret);
@@ -1357,20 +1363,20 @@ __bam_repl_print(notused1, dbtp, lsnp, notused3, notused4)
        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);
+               ch = ((u_int8_t *)argp->orig.data)[i];
+               if (isprint(ch) || ch == 0xa)
+                       putchar(ch);
                else
-                       printf("%#x ", c);
+                       printf("%#x ", ch);
        }
        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);
+               ch = ((u_int8_t *)argp->repl.data)[i];
+               if (isprint(ch) || ch == 0xa)
+                       putchar(ch);
                else
-                       printf("%#x ", c);
+                       printf("%#x ", ch);
        }
        printf("\n");
        printf("\tprefix: %lu\n", (u_long)argp->prefix);
index 85f4e8c..4e144b1 100644 (file)
@@ -1,14 +1,14 @@
 /*-
  * See the file LICENSE for redistribution information.
  *
- * Copyright (c) 1996, 1997
+ * Copyright (c) 1996, 1997, 1998
  *     Sleepycat Software.  All rights reserved.
  */
 
 #include "config.h"
 
 #ifndef lint
-static const char sccsid[] = "@(#)getlong.c    10.2 (Sleepycat) 5/1/97";
+static const char sccsid[] = "@(#)getlong.c    10.3 (Sleepycat) 4/10/98";
 #endif /* not lint */
 
 #ifndef NO_SYSTEM_INCLUDES
index 4ee9e4f..6ec007b 100644 (file)
@@ -1,23 +1,21 @@
 /*-
  * See the file LICENSE for redistribution information.
  *
- * Copyright (c) 1996, 1997
+ * Copyright (c) 1996, 1997, 1998
  *     Sleepycat Software.  All rights reserved.
  */
 
 #include "config.h"
 
 #ifndef lint
-static const char sccsid[] = "@(#)db_appinit.c 10.38 (Sleepycat) 1/7/98";
+static const char sccsid[] = "@(#)db_appinit.c 10.52 (Sleepycat) 6/2/98";
 #endif /* not lint */
 
 #ifndef NO_SYSTEM_INCLUDES
-#include <sys/param.h>
-#include <sys/stat.h>
+#include <sys/types.h>
 
 #include <ctype.h>
 #include <errno.h>
-#include <fcntl.h>
 #include <signal.h>
 #include <stdlib.h>
 #include <string.h>
@@ -34,14 +32,14 @@ static const char sccsid[] = "@(#)db_appinit.c      10.38 (Sleepycat) 1/7/98";
 #include "clib_ext.h"
 #include "common_ext.h"
 
-static int __db_home __P((DB_ENV *, const char *, int));
+static int __db_home __P((DB_ENV *, const char *, u_int32_t));
 static int __db_parse __P((DB_ENV *, char *));
-static int __db_tmp_dir __P((DB_ENV *, int));
-static int __db_tmp_open __P((DB_ENV *, char *, int *));
+static int __db_tmp_dir __P((DB_ENV *, u_int32_t));
+static int __db_tmp_open __P((DB_ENV *, u_int32_t, char *, int *));
 
 /*
  * db_version --
- *     Return verision information.
+ *     Return version information.
  */
 char *
 db_version(majverp, minverp, patchp)
@@ -65,16 +63,18 @@ db_appinit(db_home, db_config, dbenv, flags)
        const char *db_home;
        char * const *db_config;
        DB_ENV *dbenv;
-       int flags;
+       u_int32_t flags;
 {
        FILE *fp;
-       int ret;
+       int mode, ret;
        char * const *p;
        char *lp, buf[MAXPATHLEN * 2];
 
        /* Validate arguments. */
        if (dbenv == NULL)
                return (EINVAL);
+
+
 #ifdef HAVE_SPINLOCKS
 #define        OKFLAGS                                                         \
    (DB_CREATE | DB_NOMMAP | DB_THREAD | DB_INIT_LOCK | DB_INIT_LOG |   \
@@ -89,10 +89,9 @@ db_appinit(db_home, db_config, dbenv, flags)
        if ((ret = __db_fchk(dbenv, "db_appinit", flags, OKFLAGS)) != 0)
                return (ret);
 
-#define        RECOVERY_FLAGS (DB_CREATE | DB_INIT_TXN | DB_INIT_LOG)
-       if (LF_ISSET(DB_RECOVER | DB_RECOVER_FATAL) &&
-           LF_ISSET(RECOVERY_FLAGS) != RECOVERY_FLAGS)
-               return (__db_ferr(dbenv, "db_appinit", 1));
+       /* Transactions imply logging. */
+       if (LF_ISSET(DB_INIT_TXN))
+               LF_SET(DB_INIT_LOG);
 
        /* Convert the db_appinit(3) flags. */
        if (LF_ISSET(DB_THREAD))
@@ -147,47 +146,48 @@ db_appinit(db_home, db_config, dbenv, flags)
        F_SET(dbenv, DB_ENV_APPINIT);
 
        /*
-        * If we are doing recovery, remove all the regions.
+        * If we are doing recovery, remove all the old shared memory
+        * regions.
         */
        if (LF_ISSET(DB_RECOVER | DB_RECOVER_FATAL)) {
-               /* Remove all the old shared memory regions.  */
-               if ((ret = log_unlink(NULL, 1 /* force */, dbenv)) != 0)
+               if ((ret = log_unlink(NULL, 1, dbenv)) != 0)
                        goto err;
-               if ((ret = memp_unlink(NULL, 1 /* force */, dbenv)) != 0)
+               if ((ret = memp_unlink(NULL, 1, dbenv)) != 0)
                        goto err;
-               if ((ret = lock_unlink(NULL, 1 /* force */, dbenv)) != 0)
+               if ((ret = lock_unlink(NULL, 1, dbenv)) != 0)
                        goto err;
-               if ((ret = txn_unlink(NULL, 1 /* force */, dbenv)) != 0)
+               if ((ret = txn_unlink(NULL, 1, dbenv)) != 0)
                        goto err;
        }
 
-       /* Transactions imply logging. */
-       if (LF_ISSET(DB_INIT_TXN))
-               LF_SET(DB_INIT_LOG);
-
-       /* Default permissions are 0660. */
-#undef DB_DEFPERM
-#define        DB_DEFPERM      (S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP)
-
-       /* Initialize the subsystems. */
+       /*
+        * Create the new shared regions.
+        *
+        * Default permissions are read-write for both owner and group.
+        */
+       mode = __db_omode("rwrw--");
        if (LF_ISSET(DB_INIT_LOCK) && (ret = lock_open(NULL,
            LF_ISSET(DB_CREATE | DB_THREAD),
-           DB_DEFPERM, dbenv, &dbenv->lk_info)) != 0)
+           mode, dbenv, &dbenv->lk_info)) != 0)
                goto err;
        if (LF_ISSET(DB_INIT_LOG) && (ret = log_open(NULL,
            LF_ISSET(DB_CREATE | DB_THREAD),
-           DB_DEFPERM, dbenv, &dbenv->lg_info)) != 0)
+           mode, dbenv, &dbenv->lg_info)) != 0)
                goto err;
        if (LF_ISSET(DB_INIT_MPOOL) && (ret = memp_open(NULL,
            LF_ISSET(DB_CREATE | DB_MPOOL_PRIVATE | DB_NOMMAP | DB_THREAD),
-           DB_DEFPERM, dbenv, &dbenv->mp_info)) != 0)
+           mode, dbenv, &dbenv->mp_info)) != 0)
                goto err;
        if (LF_ISSET(DB_INIT_TXN) && (ret = txn_open(NULL,
            LF_ISSET(DB_CREATE | DB_THREAD | DB_TXN_NOSYNC),
-           DB_DEFPERM, dbenv, &dbenv->tx_info)) != 0)
+           mode, dbenv, &dbenv->tx_info)) != 0)
                goto err;
 
-       /* Initialize recovery. */
+       /*
+        * If the application is running with transactions, initialize the
+        * function tables.  Once that's done, do recovery for any previous
+        * run.
+        */
        if (LF_ISSET(DB_INIT_TXN)) {
                if ((ret = __bam_init_recover(dbenv)) != 0)
                        goto err;
@@ -199,12 +199,12 @@ db_appinit(db_home, db_config, dbenv, flags)
                        goto err;
                if ((ret = __txn_init_recover(dbenv)) != 0)
                        goto err;
-       }
 
-       /* Run recovery if necessary. */
-       if (LF_ISSET(DB_RECOVER | DB_RECOVER_FATAL) && (ret =
-           __db_apprec(dbenv, LF_ISSET(DB_RECOVER | DB_RECOVER_FATAL))) != 0)
-               goto err;
+               if (LF_ISSET(DB_RECOVER | DB_RECOVER_FATAL) &&
+                   (ret = __db_apprec(dbenv,
+                   LF_ISSET(DB_RECOVER | DB_RECOVER_FATAL))) != 0)
+                       goto err;
+       }
 
        return (ret);
 
@@ -282,21 +282,21 @@ db_appexit(dbenv)
  *     it in allocated space.
  *
  * PUBLIC: int __db_appname __P((DB_ENV *,
- * PUBLIC:    APPNAME, const char *, const char *, int *, char **));
+ * PUBLIC:    APPNAME, const char *, const char *, u_int32_t, int *, char **));
  */
 int
-__db_appname(dbenv, appname, dir, file, fdp, namep)
+__db_appname(dbenv, appname, dir, file, tmp_oflags, fdp, namep)
        DB_ENV *dbenv;
        APPNAME appname;
        const char *dir, *file;
+       u_int32_t tmp_oflags;
        int *fdp;
        char **namep;
 {
        DB_ENV etmp;
        size_t len;
-       int ret, slash, tmp_create, tmp_free;
+       int data_entry, ret, slash, tmp_create, tmp_free;
        const char *a, *b, *c;
-       int data_entry;
        char *p, *start;
 
        a = b = c = NULL;
@@ -349,8 +349,8 @@ __db_appname(dbenv, appname, dir, file, fdp, namep)
         *
         * DB_ENV          APPNAME         RESULT
         * -------------------------------------------
-        * null            DB_APP_TMP      <tmp>/<create>
-        * set             DB_APP_TMP      DB_HOME/DB_TMP_DIR/<create>
+        * null            DB_APP_TMP*     <tmp>/<create>
+        * set             DB_APP_TMP*     DB_HOME/DB_TMP_DIR/<create>
         */
 retry: switch (appname) {
        case DB_APP_NONE:
@@ -431,7 +431,14 @@ done:      len =
            (c == NULL ? 0 : strlen(c) + 1) +
            (file == NULL ? 0 : strlen(file) + 1);
 
-       if ((start = (char *)__db_malloc(len)) == NULL) {
+       /*
+        * Allocate space to hold the current path information, as well as any
+        * temporary space that we're going to need to create a temporary file
+        * name.
+        */
+#define        DB_TRAIL        "XXXXXX"
+       if ((start =
+           (char *)__db_malloc(len + sizeof(DB_TRAIL) + 10)) == NULL) {
                __db_err(dbenv, "%s", strerror(ENOMEM));
                if (tmp_free)
                        FREES(etmp.db_tmp_dir);
@@ -460,14 +467,15 @@ done:     len =
                FREES(etmp.db_tmp_dir);
 
        /* Create the file if so requested. */
-       if (tmp_create) {
-               ret = __db_tmp_open(dbenv, start, fdp);
+       if (tmp_create &&
+           (ret = __db_tmp_open(dbenv, tmp_oflags, start, fdp)) != 0) {
                FREES(start);
-       } else {
-               *namep = start;
-               ret = 0;
+               return (ret);
        }
-       return (ret);
+
+       if (namep != NULL)
+               *namep = start;
+       return (0);
 }
 
 /*
@@ -478,7 +486,7 @@ static int
 __db_home(dbenv, db_home, flags)
        DB_ENV *dbenv;
        const char *db_home;
-       int flags;
+       u_int32_t flags;
 {
        const char *p;
 
@@ -532,10 +540,12 @@ __db_parse(dbenv, s)
                return (ENOMEM);
 
        tp = local_s;
-       while ((name = strsep(&tp, " \t")) != NULL && *name == '\0');
+       while ((name = strsep(&tp, " \t")) != NULL && *name == '\0')
+               ;
        if (name == NULL)
                goto illegal;
-       while ((value = strsep(&tp, " \t")) != NULL && *value == '\0');
+       while ((value = strsep(&tp, " \t")) != NULL && *value == '\0')
+               ;
        if (value == NULL) {
 illegal:       ret = EINVAL;
                __db_err(dbenv, "illegal name-value pair: %s", s);
@@ -591,7 +601,7 @@ static char *sTempFolder;
 static int
 __db_tmp_dir(dbenv, flags)
        DB_ENV *dbenv;
-       int flags;
+       u_int32_t flags;
 {
        static const char * list[] = {  /* Ordered: see db_appinit(3). */
                "/var/tmp",
@@ -671,49 +681,45 @@ __db_tmp_dir(dbenv, flags)
  *     Create a temporary file.
  */
 static int
-__db_tmp_open(dbenv, dir, fdp)
+__db_tmp_open(dbenv, flags, path, fdp)
        DB_ENV *dbenv;
-       char *dir;
+       u_int32_t flags;
+       char *path;
        int *fdp;
 {
 #ifdef HAVE_SIGFILLSET
        sigset_t set, oset;
 #endif
        u_long pid;
-       size_t len;
-       int isdir, ret;
-       char *trv, buf[MAXPATHLEN];
+       int mode, isdir, ret;
+       const char *p;
+       char *trv;
 
        /*
         * Check the target directory; if you have six X's and it doesn't
         * exist, this runs for a *very* long time.
         */
-       if ((ret = __db_exists(dir, &isdir)) != 0) {
-               __db_err(dbenv, "%s: %s", dir, strerror(ret));
+       if ((ret = __db_exists(path, &isdir)) != 0) {
+               __db_err(dbenv, "%s: %s", path, strerror(ret));
                return (ret);
        }
        if (!isdir) {
-               __db_err(dbenv, "%s: %s", dir, strerror(EINVAL));
+               __db_err(dbenv, "%s: %s", path, strerror(EINVAL));
                return (EINVAL);
        }
 
        /* Build the path. */
-#define        DB_TRAIL        "/XXXXXX"
-       if ((len = strlen(dir)) + sizeof(DB_TRAIL) > sizeof(buf)) {
-               __db_err(dbenv,
-                   "tmp_open: %s: %s", buf, strerror(ENAMETOOLONG));
-               return (ENAMETOOLONG);
-       }
-       (void)strcpy(buf, dir);
-       (void)strcpy(buf + len, DB_TRAIL);
-       buf[len] = PATH_SEPARATOR[0];                   /* WIN32 */
+       for (trv = path; *trv != '\0'; ++trv)
+               ;
+       *trv = PATH_SEPARATOR[0];
+       for (p = DB_TRAIL; (*++trv = *p) != '\0'; ++p)
+               ;
 
        /*
         * Replace the X's with the process ID.  Pid should be a pid_t,
         * but we use unsigned long for portability.
         */
-       for (pid = getpid(),
-           trv = buf + len + sizeof(DB_TRAIL) - 1; *--trv == 'X'; pid /= 10)
+       for (pid = getpid(); *--trv == 'X'; pid /= 10)
                switch (pid % 10) {
                case 0: *trv = '0'; break;
                case 1: *trv = '1'; break;
@@ -728,30 +734,33 @@ __db_tmp_open(dbenv, dir, fdp)
                }
        ++trv;
 
+       /* Set up open flags and mode. */
+       LF_SET(DB_CREATE | DB_EXCL);
+       mode = __db_omode("rw----");
+
        /*
-        * Try and open a file.  We block every signal we can get our hands
+        * Try to open a file.  We block every signal we can get our hands
         * on so that, if we're interrupted at the wrong time, the temporary
         * file isn't left around -- of course, if we drop core in-between
         * the calls we'll hang forever, but that's probably okay.  ;-}
         */
 #ifdef HAVE_SIGFILLSET
-       (void)sigfillset(&set);
+       if (LF_ISSET(DB_TEMPORARY))
+               (void)sigfillset(&set);
 #endif
        for (;;) {
 #ifdef HAVE_SIGFILLSET
-               (void)sigprocmask(SIG_BLOCK, &set, &oset);
+               if (LF_ISSET(DB_TEMPORARY))
+                       (void)sigprocmask(SIG_BLOCK, &set, &oset);
 #endif
-#define        DB_TEMPOPEN     DB_CREATE | DB_EXCL | DB_TEMPORARY
-               if ((ret = __db_open(buf,
-                   DB_TEMPOPEN, DB_TEMPOPEN, S_IRUSR | S_IWUSR, fdp)) == 0) {
+               ret = __db_open(path, flags, flags, mode, fdp);
 #ifdef HAVE_SIGFILLSET
+               if (LF_ISSET(DB_TEMPORARY))
                        (void)sigprocmask(SIG_SETMASK, &oset, NULL);
 #endif
+               if (ret == 0)
                        return (0);
-               }
-#ifdef HAVE_SIGFILLSET
-               (void)sigprocmask(SIG_SETMASK, &oset, NULL);
-#endif
+
                /*
                 * XXX:
                 * If we don't get an EEXIST error, then there's something
@@ -761,7 +770,7 @@ __db_tmp_open(dbenv, dir, fdp)
                 */
                if (ret != EEXIST) {
                        __db_err(dbenv,
-                           "tmp_open: %s: %s", buf, strerror(ret));
+                           "tmp_open: %s: %s", path, strerror(ret));
                        return (ret);
                }
 
index 7a42e13..df707ea 100644 (file)
@@ -1,7 +1,7 @@
 /*-
  * See the file LICENSE for redistribution information.
  *
- * Copyright (c) 1996, 1997
+ * Copyright (c) 1996, 1997, 1998
  *     Sleepycat Software.  All rights reserved.
  */
 
@@ -9,18 +9,17 @@
 
 #ifndef lint
 static const char copyright[] =
-"@(#) Copyright (c) 1997\n\
+"@(#) Copyright (c) 1996, 1997, 1998\n\
        Sleepycat Software Inc.  All rights reserved.\n";
-static const char sccsid[] = "@(#)db_apprec.c  10.23 (Sleepycat) 1/17/98";
+static const char sccsid[] = "@(#)db_apprec.c  10.30 (Sleepycat) 5/3/98";
 #endif
 
 #ifndef NO_SYSTEM_INCLUDES
 #include <sys/types.h>
 
 #include <errno.h>
-#include <time.h>
 #include <string.h>
-#include <stdlib.h>
+#include <time.h>
 #endif
 
 #include "db_int.h"
@@ -36,18 +35,19 @@ static const char sccsid[] = "@(#)db_apprec.c       10.23 (Sleepycat) 1/17/98";
  * __db_apprec --
  *     Perform recovery.
  *
- * PUBLIC: int __db_apprec __P((DB_ENV *, int));
+ * PUBLIC: int __db_apprec __P((DB_ENV *, u_int32_t));
  */
 int
 __db_apprec(dbenv, flags)
        DB_ENV *dbenv;
-       int flags;
+       u_int32_t flags;
 {
        DBT data;
        DB_LOG *lp;
        DB_LSN ckp_lsn, first_lsn, lsn;
        time_t now;
-       int is_thread, ret;
+       u_int32_t is_thread;
+       int ret;
        void *txninfo;
 
        lp = dbenv->lg_info;
@@ -91,14 +91,14 @@ __db_apprec(dbenv, flags)
        if ((ret = log_get(lp, &ckp_lsn, &data, DB_CHECKPOINT)) != 0) {
                /*
                 * If we don't find a checkpoint, start from the beginning.
-                * If that fails, we're done.  Note, we require that there
-                * be log records if we're performing recovery, and fail if
-                * there aren't.
+                * If that fails, we're done.  Note, we do not require that
+                * there be log records if we're performing recovery.
                 */
                if ((ret = log_get(lp, &ckp_lsn, &data, DB_FIRST)) != 0) {
-                       __db_err(dbenv, "First log record not found");
                        if (ret == DB_NOTFOUND)
-                               ret = EINVAL;
+                               ret = 0;
+                       else
+                               __db_err(dbenv, "First log record not found");
                        goto out;
                }
        }
@@ -134,14 +134,17 @@ __db_apprec(dbenv, flags)
        } else
                if ((ret = __log_findckp(lp, &first_lsn)) == DB_NOTFOUND) {
                        /*
-                        * If recovery was specified, there must be log files.
-                        * If we don't find one, it's an error.  (This should
-                        * have been caught above, when a log_get() of DB_FIRST
-                        * or DB_CHECKPOINT succeeded, but paranoia is good.)
+                        * We don't require that log files exist if recovery
+                        * was specified.
                         */
-                       ret = EINVAL;
+                       ret = 0;
                        goto out;
                }
+
+       if (dbenv->db_verbose)
+               __db_err(lp->dbenv, "Recovery starting from [%lu][%lu]",
+                   (u_long)first_lsn.file, (u_long)first_lsn.offset);
+
        for (ret = log_get(lp, &lsn, &data, DB_LAST);
            ret == 0 && log_compare(&lsn, &first_lsn) > 0;
            ret = log_get(lp, &lsn, &data, DB_PREV)) {
@@ -175,21 +178,21 @@ __db_apprec(dbenv, flags)
        __log_close_files(lp);
 
        /*
-        * Now set the maximum transaction id, set the last checkpoint lsn,
-        * and the current time.  Then take a checkpoint.
+        * Now set the last checkpoint lsn and the current time,
+        * take a checkpoint, and reset the txnid.
         */
        (void)time(&now);
-       dbenv->tx_info->region->last_txnid = ((__db_txnhead *)txninfo)->maxid;
        dbenv->tx_info->region->last_ckp = ckp_lsn;
        dbenv->tx_info->region->time_ckp = (u_int32_t)now;
        if ((ret = txn_checkpoint(dbenv->tx_info, 0, 0)) != 0)
                goto out;
+       dbenv->tx_info->region->last_txnid = TXN_MINIMUM;
 
        if (dbenv->db_verbose) {
                __db_err(lp->dbenv, "Recovery complete at %.24s", ctime(&now));
-               __db_err(lp->dbenv, "%s %lu %s [%lu][%lu]",
+               __db_err(lp->dbenv, "%s %lx %s [%lu][%lu]",
                    "Maximum transaction id",
-                   (u_long)dbenv->tx_info->region->last_txnid,
+                   ((DB_TXNHEAD *)txninfo)->maxid,
                    "Recovery checkpoint",
                    (u_long)dbenv->tx_info->region->last_ckp.file,
                    (u_long)dbenv->tx_info->region->last_ckp.offset);
index e486132..cadf742 100644 (file)
@@ -1,14 +1,14 @@
 /*-
  * See the file LICENSE for redistribution information.
  *
- * Copyright (c) 1996, 1997
+ * Copyright (c) 1996, 1997, 1998
  *     Sleepycat Software.  All rights reserved.
  */
 
 #include "config.h"
 
 #ifndef lint
-static const char sccsid[] = "@(#)db_byteorder.c       10.4 (Sleepycat) 9/4/97";
+static const char sccsid[] = "@(#)db_byteorder.c       10.5 (Sleepycat) 4/10/98";
 #endif /* not lint */
 
 #ifndef NO_SYSTEM_INCLUDES
index fc59aad..98a4142 100644 (file)
@@ -1,14 +1,14 @@
 /*-
  * See the file LICENSE for redistribution information.
  *
- * Copyright (c) 1996, 1997
+ * Copyright (c) 1996, 1997, 1998
  *     Sleepycat Software.  All rights reserved.
  */
 
 #include "config.h"
 
 #ifndef lint
-static const char sccsid[] = "@(#)db_err.c     10.21 (Sleepycat) 1/13/98";
+static const char sccsid[] = "@(#)db_err.c     10.25 (Sleepycat) 5/2/98";
 #endif /* not lint */
 
 #ifndef NO_SYSTEM_INCLUDES
@@ -26,6 +26,7 @@ static const char sccsid[] = "@(#)db_err.c    10.21 (Sleepycat) 1/13/98";
 #include "db_int.h"
 #include "common_ext.h"
 
+static int __db_keyempty __P((const DB_ENV *));
 static int __db_rdonly __P((const DB_ENV *, const char *));
 
 /*
@@ -81,11 +82,11 @@ __db_err(dbenv, fmt, va_alist)
  * appears before the assignment in the __db__panic() call.
  */
 static int __db_ecursor __P((DB *, DB_TXN *, DBC **));
-static int __db_edel __P((DB *, DB_TXN *, DBT *, int));
+static int __db_edel __P((DB *, DB_TXN *, DBT *, u_int32_t));
 static int __db_efd __P((DB *, int *));
-static int __db_egp __P((DB *, DB_TXN *, DBT *, DBT *, int));
-static int __db_estat __P((DB *, void *, void *(*)(size_t), int));
-static int __db_esync __P((DB *, int));
+static int __db_egp __P((DB *, DB_TXN *, DBT *, DBT *, u_int32_t));
+static int __db_estat __P((DB *, void *, void *(*)(size_t), u_int32_t));
+static int __db_esync __P((DB *, u_int32_t));
 
 /*
  * __db_ecursor --
@@ -113,7 +114,7 @@ __db_edel(a, b, c, d)
        DB *a;
        DB_TXN *b;
        DBT *c;
-       int d;
+       u_int32_t d;
 {
        COMPQUIET(a, NULL);
        COMPQUIET(b, NULL);
@@ -147,7 +148,7 @@ __db_egp(a, b, c, d, e)
        DB *a;
        DB_TXN *b;
        DBT *c, *d;
-       int e;
+       u_int32_t e;
 {
        COMPQUIET(a, NULL);
        COMPQUIET(b, NULL);
@@ -167,7 +168,7 @@ __db_estat(a, b, c, d)
        DB *a;
        void *b;
        void *(*c) __P((size_t));
-       int d;
+       u_int32_t d;
 {
        COMPQUIET(a, NULL);
        COMPQUIET(b, NULL);
@@ -184,7 +185,7 @@ __db_estat(a, b, c, d)
 static int
 __db_esync(a, b)
        DB *a;
-       int b;
+       u_int32_t b;
 {
        COMPQUIET(a, NULL);
        COMPQUIET(b, 0);
@@ -208,6 +209,10 @@ __db_panic(dbp)
         *
         * We should call mpool and have it shut down the file, so we get
         * other processes sharing this file as well.
+        *
+        *      Chaos reigns within.
+        *      Reflect, repent, and reboot.
+        *      Order shall return.
         */
        dbp->cursor = __db_ecursor;
        dbp->del = __db_edel;
@@ -235,13 +240,13 @@ __db_panic(dbp)
  * __db_fchk --
  *     General flags checking routine.
  *
- * PUBLIC: int __db_fchk __P((DB_ENV *, const char *, int, int));
+ * PUBLIC: int __db_fchk __P((DB_ENV *, const char *, u_int32_t, u_int32_t));
  */
 int
 __db_fchk(dbenv, name, flags, ok_flags)
        DB_ENV *dbenv;
        const char *name;
-       int flags, ok_flags;
+       u_int32_t flags, ok_flags;
 {
        DB_CHECK_FLAGS(dbenv, name, flags, ok_flags);
        return (0);
@@ -251,13 +256,14 @@ __db_fchk(dbenv, name, flags, ok_flags)
  * __db_fcchk --
  *     General combination flags checking routine.
  *
- * PUBLIC: int __db_fcchk __P((DB_ENV *, const char *, int, int, int));
+ * PUBLIC: int __db_fcchk
+ * PUBLIC:    __P((DB_ENV *, const char *, u_int32_t, u_int32_t, u_int32_t));
  */
 int
 __db_fcchk(dbenv, name, flags, flag1, flag2)
        DB_ENV *dbenv;
        const char *name;
-       int flags, flag1, flag2;
+       u_int32_t flags, flag1, flag2;
 {
        DB_CHECK_FCOMBO(dbenv, name, flags, flag1, flag2);
        return (0);
@@ -267,12 +273,13 @@ __db_fcchk(dbenv, name, flags, flag1, flag2)
  * __db_cdelchk --
  *     Common cursor delete argument checking routine.
  *
- * PUBLIC: int __db_cdelchk __P((const DB *, int, int, int));
+ * PUBLIC: int __db_cdelchk __P((const DB *, u_int32_t, int, int));
  */
 int
 __db_cdelchk(dbp, flags, isrdonly, isvalid)
        const DB *dbp;
-       int flags, isrdonly, isvalid;
+       u_int32_t flags;
+       int isrdonly, isvalid;
 {
        /* Check for changes to a read-only tree. */
        if (isrdonly)
@@ -292,17 +299,18 @@ __db_cdelchk(dbp, flags, isrdonly, isvalid)
  * __db_cgetchk --
  *     Common cursor get argument checking routine.
  *
- * PUBLIC: int __db_cgetchk __P((const DB *, DBT *, DBT *, int, int));
+ * PUBLIC: int __db_cgetchk __P((const DB *, DBT *, DBT *, u_int32_t, int));
  */
 int
 __db_cgetchk(dbp, key, data, flags, isvalid)
        const DB *dbp;
        DBT *key, *data;
-       int flags, isvalid;
+       u_int32_t flags;
+       int isvalid;
 {
-       int check_key;
+       int key_einval, key_flags;
 
-       check_key = 0;
+       key_flags = key_einval = 0;
 
        /* Check for invalid dbc->c_get() function flags. */
        switch (flags) {
@@ -311,10 +319,13 @@ __db_cgetchk(dbp, key, data, flags, isvalid)
        case DB_LAST:
        case DB_NEXT:
        case DB_PREV:
+               key_flags = 1;
+               break;
        case DB_SET_RANGE:
-               check_key = 1;
+               key_einval = key_flags = 1;
                break;
        case DB_SET:
+               key_einval = 1;
                break;
        case DB_GET_RECNO:
                if (!F_ISSET(dbp, DB_BT_RECNUM))
@@ -323,14 +334,14 @@ __db_cgetchk(dbp, key, data, flags, isvalid)
        case DB_SET_RECNO:
                if (!F_ISSET(dbp, DB_BT_RECNUM))
                        goto err;
-               check_key = 1;
+               key_einval = key_flags = 1;
                break;
        default:
 err:           return (__db_ferr(dbp->dbenv, "c_get", 0));
        }
 
        /* Check for invalid key/data flags. */
-       if (check_key)
+       if (key_flags)
                DB_CHECK_FLAGS(dbp->dbenv, "key", key->flags,
                    DB_DBT_MALLOC | DB_DBT_USERMEM | DB_DBT_PARTIAL);
        DB_CHECK_FLAGS(dbp->dbenv, "data", data->flags,
@@ -340,11 +351,15 @@ err:              return (__db_ferr(dbp->dbenv, "c_get", 0));
        if (F_ISSET(dbp, DB_AM_THREAD)) {
                if (!F_ISSET(data, DB_DBT_USERMEM | DB_DBT_MALLOC))
                        return (__db_ferr(dbp->dbenv, "threaded data", 1));
-               if (check_key &&
+               if (key_flags &&
                    !F_ISSET(key, DB_DBT_USERMEM | DB_DBT_MALLOC))
                        return (__db_ferr(dbp->dbenv, "threaded key", 1));
        }
 
+       /* Check for missing keys. */
+       if (key_einval && (key->data == NULL || key->size == 0))
+               return (__db_keyempty(dbp->dbenv));
+
        /*
         * The cursor must be initialized for DB_CURRENT, return -1 for an
         * invalid cursor, otherwise 0.
@@ -357,23 +372,24 @@ err:              return (__db_ferr(dbp->dbenv, "c_get", 0));
  *     Common cursor put argument checking routine.
  *
  * PUBLIC: int __db_cputchk __P((const DB *,
- * PUBLIC:    const DBT *, DBT *, int, int, int));
+ * PUBLIC:    const DBT *, DBT *, u_int32_t, int, int));
  */
 int
 __db_cputchk(dbp, key, data, flags, isrdonly, isvalid)
        const DB *dbp;
        const DBT *key;
        DBT *data;
-       int flags, isrdonly, isvalid;
+       u_int32_t flags;
+       int isrdonly, isvalid;
 {
-       int check_key;
+       int key_einval, key_flags;
 
        /* Check for changes to a read-only tree. */
        if (isrdonly)
                return (__db_rdonly(dbp->dbenv, "c_put"));
 
        /* Check for invalid dbc->c_put() function flags. */
-       check_key = 0;
+       key_einval = key_flags = 0;
        switch (flags) {
        case DB_AFTER:
        case DB_BEFORE:
@@ -388,19 +404,23 @@ __db_cputchk(dbp, key, data, flags, isrdonly, isvalid)
        case DB_KEYLAST:
                if (dbp->type == DB_RECNO)
                        goto err;
-               check_key = 1;
+               key_einval = key_flags = 1;
                break;
        default:
 err:           return (__db_ferr(dbp->dbenv, "c_put", 0));
        }
 
        /* Check for invalid key/data flags. */
-       if (check_key)
+       if (key_flags)
                DB_CHECK_FLAGS(dbp->dbenv, "key", key->flags,
                    DB_DBT_MALLOC | DB_DBT_USERMEM | DB_DBT_PARTIAL);
        DB_CHECK_FLAGS(dbp->dbenv, "data", data->flags,
            DB_DBT_MALLOC | DB_DBT_USERMEM | DB_DBT_PARTIAL);
 
+       /* Check for missing keys. */
+       if (key_einval && (key->data == NULL || key->size == 0))
+               return (__db_keyempty(dbp->dbenv));
+
        /*
         * The cursor must be initialized for anything other than DB_KEYFIRST
         * and DB_KEYLAST, return -1 for an invalid cursor, otherwise 0.
@@ -413,12 +433,14 @@ err:              return (__db_ferr(dbp->dbenv, "c_put", 0));
  * __db_delchk --
  *     Common delete argument checking routine.
  *
- * PUBLIC: int __db_delchk __P((const DB *, int, int));
+ * PUBLIC: int __db_delchk __P((const DB *, DBT *, u_int32_t, int));
  */
 int
-__db_delchk(dbp, flags, isrdonly)
+__db_delchk(dbp, key, flags, isrdonly)
        const DB *dbp;
-       int flags, isrdonly;
+       DBT *key;
+       u_int32_t flags;
+       int isrdonly;
 {
        /* Check for changes to a read-only tree. */
        if (isrdonly)
@@ -427,6 +449,10 @@ __db_delchk(dbp, flags, isrdonly)
        /* Check for invalid db->del() function flags. */
        DB_CHECK_FLAGS(dbp->dbenv, "delete", flags, 0);
 
+       /* Check for missing keys. */
+       if (key->data == NULL || key->size == 0)
+               return (__db_keyempty(dbp->dbenv));
+
        return (0);
 }
 
@@ -434,14 +460,14 @@ __db_delchk(dbp, flags, isrdonly)
  * __db_getchk --
  *     Common get argument checking routine.
  *
- * PUBLIC: int __db_getchk __P((const DB *, const DBT *, DBT *, int));
+ * PUBLIC: int __db_getchk __P((const DB *, const DBT *, DBT *, u_int32_t));
  */
 int
 __db_getchk(dbp, key, data, flags)
        const DB *dbp;
        const DBT *key;
        DBT *data;
-       int flags;
+       u_int32_t flags;
 {
        /* Check for invalid db->get() function flags. */
        DB_CHECK_FLAGS(dbp->dbenv,
@@ -457,6 +483,10 @@ __db_getchk(dbp, key, data, flags)
            !F_ISSET(data, DB_DBT_MALLOC | DB_DBT_USERMEM))
                return (__db_ferr(dbp->dbenv, "threaded data", 1));
 
+       /* Check for missing keys. */
+       if (key->data == NULL || key->size == 0)
+               return (__db_keyempty(dbp->dbenv));
+
        return (0);
 }
 
@@ -464,14 +494,16 @@ __db_getchk(dbp, key, data, flags)
  * __db_putchk --
  *     Common put argument checking routine.
  *
- * PUBLIC: int __db_putchk __P((const DB *, DBT *, const DBT *, int, int, int));
+ * PUBLIC: int __db_putchk
+ * PUBLIC:    __P((const DB *, DBT *, const DBT *, u_int32_t, int, int));
  */
 int
 __db_putchk(dbp, key, data, flags, isrdonly, isdup)
        const DB *dbp;
        DBT *key;
        const DBT *data;
-       int flags, isrdonly, isdup;
+       u_int32_t flags;
+       int isrdonly, isdup;
 {
        /* Check for changes to a read-only tree. */
        if (isrdonly)
@@ -488,12 +520,17 @@ __db_putchk(dbp, key, data, flags, isrdonly, isdup)
        DB_CHECK_FCOMBO(dbp->dbenv,
            "data", data->flags, DB_DBT_MALLOC, DB_DBT_USERMEM);
 
+       /* Check for missing keys. */
+       if (key->data == NULL || key->size == 0)
+               return (__db_keyempty(dbp->dbenv));
+
        /* Check for partial puts in the presence of duplicates. */
        if (isdup && F_ISSET(data, DB_DBT_PARTIAL)) {
                __db_err(dbp->dbenv,
 "a partial put in the presence of duplicates requires a cursor operation");
                return (EINVAL);
        }
+
        return (0);
 }
 
@@ -501,12 +538,12 @@ __db_putchk(dbp, key, data, flags, isrdonly, isdup)
  * __db_statchk --
  *     Common stat argument checking routine.
  *
- * PUBLIC: int __db_statchk __P((const DB *, int));
+ * PUBLIC: int __db_statchk __P((const DB *, u_int32_t));
  */
 int
 __db_statchk(dbp, flags)
        const DB *dbp;
-       int flags;
+       u_int32_t flags;
 {
        /* Check for invalid db->stat() function flags. */
        DB_CHECK_FLAGS(dbp->dbenv, "stat", flags, DB_RECORDCOUNT);
@@ -522,12 +559,12 @@ __db_statchk(dbp, flags)
  * __db_syncchk --
  *     Common sync argument checking routine.
  *
- * PUBLIC: int __db_syncchk __P((const DB *, int));
+ * PUBLIC: int __db_syncchk __P((const DB *, u_int32_t));
  */
 int
 __db_syncchk(dbp, flags)
        const DB *dbp;
-       int flags;
+       u_int32_t flags;
 {
        /* Check for invalid db->sync() function flags. */
        DB_CHECK_FLAGS(dbp->dbenv, "sync", flags, 0);
@@ -542,13 +579,13 @@ __db_syncchk(dbp, flags)
  * PUBLIC: int __db_ferr __P((const DB_ENV *, const char *, int));
  */
 int
-__db_ferr(dbenv, name, combo)
+__db_ferr(dbenv, name, iscombo)
        const DB_ENV *dbenv;
        const char *name;
-       int combo;
+       int iscombo;
 {
        __db_err(dbenv, "illegal flag %sspecified to %s",
-           combo ? "combination " : "", name);
+           iscombo ? "combination " : "", name);
        return (EINVAL);
 }
 
@@ -564,3 +601,15 @@ __db_rdonly(dbenv, name)
        __db_err(dbenv, "%s: attempt to modify a read-only tree", name);
        return (EACCES);
 }
+
+/*
+ * __db_keyempty --
+ *     Common missing or empty key value message.
+ */
+static int
+__db_keyempty(dbenv)
+       const DB_ENV *dbenv;
+{
+       __db_err(dbenv, "missing or empty key value specified");
+       return (EINVAL);
+}
index 9af0111..d6b14f5 100644 (file)
@@ -1,7 +1,7 @@
 /*-
  * See the file LICENSE for redistribution information.
  *
- * Copyright (c) 1996, 1997
+ * Copyright (c) 1996, 1997, 1998
  *     Sleepycat Software.  All rights reserved.
  */
 /*
@@ -43,7 +43,7 @@
 #include "config.h"
 
 #ifndef lint
-static const char sccsid[] = "@(#)db_log2.c    10.3 (Sleepycat) 6/21/97";
+static const char sccsid[] = "@(#)db_log2.c    10.5 (Sleepycat) 4/26/98";
 #endif /* not lint */
 
 #ifndef NO_SYSTEM_INCLUDES
@@ -63,6 +63,7 @@ __db_log2(num)
        u_int32_t i, limit;
 
        limit = 1;
-       for (i = 0; limit < num; limit = limit << 1, i++);
+       for (i = 0; limit < num; limit = limit << 1, i++)
+               ;
        return (i);
 }
index 02d939e..6d15f7f 100644 (file)
@@ -1,59 +1,20 @@
 /*-
  * See the file LICENSE for redistribution information.
  *
- * Copyright (c) 1996, 1997
+ * Copyright (c) 1996, 1997, 1998
  *     Sleepycat Software.  All rights reserved.
  */
-/*
- * Copyright (c) 1995, 1996
- *     The President and Fellows of Harvard University.  All rights reserved.
- *
- * This code is derived from software contributed to Harvard by
- * Margo Seltzer.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- *    must display the following acknowledgement:
- *     This product includes software developed by the University of
- *     California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
- *    may be used to endorse or promote products derived from this software
- *    without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
 
 #include "config.h"
 
 #ifndef lint
-static const char sccsid[] = "@(#)db_region.c  10.21 (Sleepycat) 1/16/98";
+static const char sccsid[] = "@(#)db_region.c  10.46 (Sleepycat) 5/26/98";
 #endif /* not lint */
 
 #ifndef NO_SYSTEM_INCLUDES
 #include <sys/types.h>
-#include <sys/stat.h>
 
 #include <errno.h>
-#include <fcntl.h>
-#include <stdio.h>
-#include <stdlib.h>
 #include <string.h>
 #include <unistd.h>
 #endif
@@ -61,548 +22,840 @@ static const char sccsid[] = "@(#)db_region.c     10.21 (Sleepycat) 1/16/98";
 #include "db_int.h"
 #include "common_ext.h"
 
-static int __db_rmap __P((DB_ENV *, int, size_t, void *));
+static int __db_growregion __P((REGINFO *, size_t));
 
 /*
- * __db_rcreate --
- *
- * Common interface for creating a shared region.  Handles synchronization
- * across multiple processes.
- *
- * The dbenv contains the environment for this process, including naming
- * information.  The path argument represents the parameters passed to
- * the open routines and may be either a file or a directory.  If it is
- * a directory, it must exist.  If it is a file, then the file parameter
- * must be NULL, otherwise, file is the name to be created inside the
- * directory path.
- *
- * The function returns a pointer to the shared region that has been mapped
- * into memory, NULL on error.
+ * __db_rattach --
+ *     Optionally create and attach to a shared memory region.
  *
- * PUBLIC: int __db_rcreate __P((DB_ENV *, APPNAME,
- * PUBLIC:    const char *, const char *, int, size_t, int, int *, void *));
+ * PUBLIC: int __db_rattach __P((REGINFO *));
  */
 int
-__db_rcreate(dbenv, appname, path, file, mode, size, oflags, fdp, retp)
-       DB_ENV *dbenv;
-       APPNAME appname;
-       const char *path, *file;
-       int mode, oflags, *fdp;
-       size_t size;
-       void *retp;
+__db_rattach(infop)
+       REGINFO *infop;
 {
-       RLAYOUT *rp;
-       int fd, ret;
-       char *name;
+       RLAYOUT *rlp, rl;
+       size_t grow_region, size;
+       ssize_t nr, nw;
+       u_int32_t flags, mbytes, bytes;
+       u_int8_t *p;
+       int malloc_possible, ret, retry_cnt;
+
+       grow_region = 0;
+       malloc_possible = 1;
+       ret = retry_cnt = 0;
+
+       /* Round off the requested size to the next page boundary. */
+       DB_ROUNDOFF(infop->size);
+
+       /* Some architectures have hard limits on the maximum region size. */
+#ifdef DB_REGIONSIZE_MAX
+       if (infop->size > DB_REGIONSIZE_MAX) {
+               __db_err(infop->dbenv, "__db_rattach: cache size too large");
+               return (EINVAL);
+       }
+#endif
 
-       fd = -1;
-       rp = NULL;
+       /* Intialize the return information in the REGINFO structure. */
+loop:  infop->addr = NULL;
+       infop->fd = -1;
+       infop->segid = INVALID_SEGID;
+       if (infop->name != NULL) {
+               FREES(infop->name);
+               infop->name = NULL;
+       }
+       F_CLR(infop, REGION_CANGROW | REGION_CREATED);
 
+#ifndef HAVE_SPINLOCKS
        /*
-        * Get the filename -- note, if it's a temporary file, it will
-        * be created by the underlying temporary file creation code,
-        * so we have to check the file descriptor to be sure it's an
-        * error.
+        * XXX
+        * Lacking spinlocks, we must have a file descriptor for fcntl(2)
+        * locking, which implies using mmap(2) to map in a regular file.
+        * (Theoretically, we could probably get a file descriptor to lock
+        * other types of shared regions, but I don't see any reason to
+        * bother.)
         */
-       if ((ret = __db_appname(dbenv, appname, path, file, &fd, &name)) != 0)
-               return (ret);
+       malloc_possible = 0;
+#endif
 
+#ifdef __hppa
        /*
-        * Now open the file. We need to make sure that multiple processes
-        * that attempt to create the region at the same time are properly
-        * ordered, so we open it DB_EXCL and DB_CREATE so two simultaneous
-        * attempts to create the region will return failure in one of the
-        * attempts.
+        * XXX
+        * HP-UX won't permit mutexes to live in anything but shared memory.
+        * Instantiate a shared region file on that architecture, regardless.
         */
-       oflags |= DB_CREATE | DB_EXCL;
-       if (fd == -1 &&
-           (ret = __db_open(name, oflags, oflags, mode, &fd)) != 0) {
-               if (ret != EEXIST)
-                       __db_err(dbenv,
-                           "region create: %s: %s", name, strerror(ret));
-               goto err;
+       malloc_possible = 0;
+#endif
+       /*
+        * If a region is truly private, malloc the memory.  That's faster
+        * than either anonymous memory or a shared file.
+        */
+       if (malloc_possible && F_ISSET(infop, REGION_PRIVATE)) {
+               if ((infop->addr = __db_malloc(infop->size)) == NULL)
+                       return (ENOMEM);
+
+               /*
+                * It's sometimes significantly faster to page-fault in all
+                * of the region's pages before we run the application, as
+                * we can see fairly nasty side-effects when we page-fault
+                * while holding various locks, i.e., the lock takes a long
+                * time, and other threads convoy behind the lock holder.
+                */
+               if (DB_GLOBAL(db_region_init))
+                       for (p = infop->addr;
+                           p < (u_int8_t *)infop->addr + infop->size;
+                           p += DB_VMPAGESIZE)
+                               p[0] = '\0';
+
+               F_SET(infop, REGION_CREATED | REGION_MALLOC);
+               goto region_init;
        }
-       *fdp = fd;
 
-       /* Grow the region to the correct size. */
-       if ((ret = __db_rgrow(dbenv, fd, size)) != 0)
-               goto err;
+       /*
+        * Get the name of the region (creating the file if a temporary file
+        * is being used).  The dbenv contains the current DB environment,
+        * including naming information.  The path argument may be a file or
+        * a directory.  If path is a directory, it must exist and file is the
+        * file name to be created inside the directory.  If path is a file,
+        * then file must be NULL.
+        */
+       if ((ret = __db_appname(infop->dbenv, infop->appname, infop->path,
+           infop->file, infop->dbflags, &infop->fd, &infop->name)) != 0)
+               return (ret);
+       if (infop->fd != -1)
+               F_SET(infop, REGION_CREATED);
 
-       /* Map the region in. */
-       if ((ret = __db_rmap(dbenv, fd, size, &rp)) != 0)
-               goto err;
+       /*
+        * Try to create the file, if we have authority.  We have to make sure
+        * that multiple threads/processes attempting to simultaneously create
+        * the region are properly ordered, so we open it using DB_CREATE and
+        * DB_EXCL, so two attempts to create the region will return failure in
+        * one.
+        */
+       if (infop->fd == -1 && infop->dbflags & DB_CREATE) {
+               flags = infop->dbflags;
+               LF_SET(DB_EXCL);
+               if ((ret = __db_open(infop->name,
+                   flags, flags, infop->mode, &infop->fd)) == 0)
+                       F_SET(infop, REGION_CREATED);
+               else
+                       if (ret != EEXIST)
+                               goto errmsg;
+       }
 
-       /* Initialize the region. */
-       if ((ret = __db_rinit(dbenv, rp, fd, size, 1)) != 0)
-               goto err;
+       /* If we couldn't create the file, try and open it. */
+       if (infop->fd == -1) {
+               flags = infop->dbflags;
+               LF_CLR(DB_CREATE | DB_EXCL);
+               if ((ret = __db_open(infop->name,
+                   flags, flags, infop->mode, &infop->fd)) != 0)
+                       goto errmsg;
+       }
 
-       if (name != NULL)
-               FREES(name);
+       /*
+        * There are three cases we support:
+        *    1. Named anonymous memory (shmget(2)).
+        *    2. Unnamed anonymous memory (mmap(2): MAP_ANON/MAP_ANONYMOUS).
+        *    3. Memory backed by a regular file (mmap(2)).
+        *
+        * We instantiate a backing file in all cases, which contains at least
+        * the RLAYOUT structure, and in case #4, contains the actual region.
+        * This is necessary for a couple of reasons:
+        *
+        * First, the mpool region uses temporary files to name regions, and
+        * since you may have multiple regions in the same directory, we need
+        * a filesystem name to ensure that they don't collide.
+        *
+        * Second, applications are allowed to forcibly remove regions, even
+        * if they don't know anything about them other than the name.  If a
+        * region is backed by anonymous memory, there has to be some way for
+        * the application to find out that information, and, in some cases,
+        * determine ID information for the anonymous memory.
+        */
+       if (F_ISSET(infop, REGION_CREATED)) {
+               /*
+                * If we're using anonymous memory to back this region, set
+                * the flag.
+                */
+               if (DB_GLOBAL(db_region_anon))
+                       F_SET(infop, REGION_ANONYMOUS);
 
-       *(void **)retp = rp;
-       return (0);
+               /*
+                * If we're using a regular file to back a region we created,
+                * grow it to the specified size.
+                */
+               if (!DB_GLOBAL(db_region_anon) &&
+                   (ret = __db_growregion(infop, infop->size)) != 0)
+                       goto err;
+       } else {
+               /*
+                * If we're joining a region, figure out what it looks like.
+                *
+                * XXX
+                * We have to figure out if the file is a regular file backing
+                * a region that we want to map into our address space, or a
+                * file with the information we need to find a shared anonymous
+                * region that we want to map into our address space.
+                *
+                * All this noise is because some systems don't have a coherent
+                * VM and buffer cache, and worse, if you mix operations on the
+                * VM and buffer cache, half the time you hang the system.
+                *
+                * There are two possibilities.  If the file is the size of an
+                * RLAYOUT structure, then we know that the real region is in
+                * shared memory, because otherwise it would be bigger.  (As
+                * the RLAYOUT structure size is smaller than a disk sector,
+                * the only way it can be this size is if deliberately written
+                * that way.)  In which case, retrieve the information we need
+                * from the RLAYOUT structure and use it to acquire the shared
+                * memory.
+                *
+                * If the structure is larger than an RLAYOUT structure, then
+                * the file is backing the shared memory region, and we use
+                * the current size of the file without reading any information
+                * from the file itself so that we don't confuse the VM.
+                *
+                * And yes, this makes me want to take somebody and kill them,
+                * but I can't think of any other solution.
+                */
+               if ((ret = __db_ioinfo(infop->name,
+                   infop->fd, &mbytes, &bytes, NULL)) != 0)
+                       goto errmsg;
+               size = mbytes * MEGABYTE + bytes;
+
+               if (size <= sizeof(RLAYOUT)) {
+                       /*
+                        * If the size is too small, the read fails or the
+                        * valid flag is incorrect, assume it's because the
+                        * RLAYOUT information hasn't been written out yet,
+                        * and retry.
+                        */
+                       if (size < sizeof(RLAYOUT))
+                               goto retry;
+                       if ((ret =
+                           __db_read(infop->fd, &rl, sizeof(rl), &nr)) != 0)
+                               goto retry;
+                       if (rl.valid != DB_REGIONMAGIC)
+                               goto retry;
+
+                       /* Copy the size, memory id and characteristics. */
+                       size = rl.size;
+                       infop->segid = rl.segid;
+                       if (F_ISSET(&rl, REGION_ANONYMOUS))
+                               F_SET(infop, REGION_ANONYMOUS);
+               }
 
-err:   if (fd != -1) {
-               if (rp != NULL)
-                       (void)__db_unmap(rp, rp->size);
-               (void)__db_unlink(name);
-               (void)__db_close(fd);
+               /*
+                * If the region is larger than we think, that's okay, use the
+                * current size.  If it's smaller than we think, and we were
+                * just using the default size, that's okay, use the current
+                * size.  If it's smaller than we think and we really care,
+                * save the size and we'll catch that further down -- we can't
+                * correct it here because we have to have a lock to grow the
+                * region.
+                */
+               if (infop->size > size && !F_ISSET(infop, REGION_SIZEDEF))
+                       grow_region = infop->size;
+               infop->size = size;
        }
-       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;
 
-       COMPQUIET(dbenv, NULL);
+       /*
+        * Map the region into our address space.  If we're creating it, the
+        * underlying routines will make it the right size.
+        *
+        * There are at least two cases where we can "reasonably" fail when
+        * we attempt to map in the region.  On Windows/95, closing the last
+        * reference to a region causes it to be zeroed out.  On UNIX, when
+        * using the shmget(2) interfaces, the region will no longer exist
+        * if the system was rebooted.  In these cases, the underlying map call
+        * returns EAGAIN, and we *remove* our file and try again.  There are
+        * obvious races in doing this, but it should eventually settle down
+        * to a winner and then things should proceed normally.
+        */
+       if ((ret = __db_mapregion(infop->name, infop)) != 0)
+               if (ret == EAGAIN) {
+                       /*
+                        * Pretend we created the region even if we didn't so
+                        * that our error processing unlinks it.
+                        */
+                       F_SET(infop, REGION_CREATED);
+                       ret = 0;
+                       goto retry;
+               } else
+                       goto err;
 
+region_init:
        /*
-        * Initialize the common information.
+        * Initialize the common region information.
         *
         * !!!
         * We have to order the region creates so that two processes don't try
-        * to simultaneously create the region and so that processes that are
-        * joining the region never see inconsistent data.  We'd like to play
-        * file permissions games, but we can't because WNT filesystems won't
-        * open a file mode 0.
-        *
-        * 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.)
+        * to simultaneously create the region.  This is handled by using the
+        * DB_CREATE and DB_EXCL flags when we create the "backing" region file.
         *
-        * 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
-        * been initialized in which case an attempt to get it could lead to
-        * 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.
-        *
-        * We also make sure to check the return of __db_mutex_lock() here,
-        * even though we don't usually check elsewhere.  This is the first
-        * lock we attempt to acquire, and if it fails we have to know.  (It
-        * can fail -- SunOS, using fcntl(2) for locking, with an in-memory
-        * filesystem specified as the database home.)
+        * We also have to order region joins so that processes joining regions
+        * never see inconsistent data.  We'd like to play permissions games
+        * with the backing file, but we can't because WNT filesystems won't
+        * open a file mode 0.
         */
-       __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);
+       rlp = (RLAYOUT *)infop->addr;
+       if (F_ISSET(infop, REGION_CREATED)) {
+               /*
+                * The process creating the region acquires a lock before it
+                * sets the valid flag.  Any processes joining the region will
+                * check the valid flag before acquiring the lock.
+                *
+                * Check the return of __db_mutex_init() and __db_mutex_lock(),
+                * even though we don't usually check elsewhere.  This is the
+                * first lock we initialize and acquire, and we have to know if
+                * it fails.  (It CAN fail, e.g., SunOS, when using fcntl(2)
+                * for locking, with an in-memory filesystem specified as the
+                * database home.)
+                */
+               if ((ret = __db_mutex_init(&rlp->lock,
+                   MUTEX_LOCK_OFFSET(rlp, &rlp->lock))) != 0 ||
+                   (ret = __db_mutex_lock(&rlp->lock, infop->fd)) != 0)
+                       goto err;
 
-       return (0);
-}
+               /* Initialize the remaining region information. */
+               rlp->refcnt = 1;
+               rlp->size = infop->size;
+               db_version(&rlp->majver, &rlp->minver, &rlp->patch);
+               rlp->segid = infop->segid;
+               rlp->flags = 0;
+               if (F_ISSET(infop, REGION_ANONYMOUS))
+                       F_SET(rlp, REGION_ANONYMOUS);
 
-/*
- * __db_ropen --
- *     Construct the name of a file, open it and map it in.
- *
- * PUBLIC: int __db_ropen __P((DB_ENV *,
- * PUBLIC:    APPNAME, const char *, const char *, int, int *, void *));
- */
-int
-__db_ropen(dbenv, appname, path, file, flags, fdp, retp)
-       DB_ENV *dbenv;
-       APPNAME appname;
-       const char *path, *file;
-       int flags, *fdp;
-       void *retp;
-{
-       RLAYOUT *rp;
-       size_t size;
-       u_int32_t mbytes, bytes;
-       int fd, ret;
-       char *name;
+               /*
+                * Fill in the valid field last -- use a magic number, memory
+                * may not be zero-filled, and we want to minimize the chance
+                * for collision.
+                */
+               rlp->valid = DB_REGIONMAGIC;
 
-       fd = -1;
-       rp = NULL;
+               /*
+                * If the region is anonymous, write the RLAYOUT information
+                * into the backing file so that future region join and unlink
+                * calls can find it.
+                *
+                * XXX
+                * We MUST do the seek before we do the write.  On Win95, while
+                * closing the last reference to an anonymous shared region
+                * doesn't discard the region, it does zero it out.  So, the
+                * REGION_CREATED may be set, but the file may have already
+                * been written and the file descriptor may be at the end of
+                * the file.
+                */
+               if (F_ISSET(infop, REGION_ANONYMOUS)) {
+                       if ((ret = __db_seek(infop->fd, 0, 0, 0, 0, 0)) != 0)
+                               goto err;
+                       if ((ret =
+                           __db_write(infop->fd, rlp, sizeof(*rlp), &nw)) != 0)
+                               goto err;
+               }
+       } else {
+               /*
+                * Check the valid flag to ensure the region is initialized.
+                * If the valid flag has not been set, the mutex may not have
+                * been initialized, and an attempt to get it could lead to
+                * random behavior.
+                */
+               if (rlp->valid != DB_REGIONMAGIC)
+                       goto retry;
 
-       /* Get the filename. */
-       if ((ret = __db_appname(dbenv, appname, path, file, NULL, &name)) != 0)
-               return (ret);
+               /* Get the region lock. */
+               (void)__db_mutex_lock(&rlp->lock, infop->fd);
 
-       /* Open the file. */
-       if ((ret = __db_open(name, flags, DB_MUTEXDEBUG, 0, &fd)) != 0) {
-               __db_err(dbenv, "region open: %s: %s", name, strerror(ret));
-               goto err2;
-       }
+               /*
+                * We now own the region.  There are a couple of things that
+                * may have gone wrong, however.
+                *
+                * Problem #1: while we were waiting for the lock, the region
+                * was deleted.  Detected by re-checking the valid flag, since
+                * it's cleared by the delete region routines.
+                */
+               if (rlp->valid != DB_REGIONMAGIC) {
+                       (void)__db_mutex_unlock(&rlp->lock, infop->fd);
+                       goto retry;
+               }
 
-       *fdp = fd;
+               /*
+                * Problem #2: We want a bigger region than has previously been
+                * created.  Detected by checking if the region is smaller than
+                * our caller requested.  If it is, we grow the region, (which
+                * does the detach and re-attach for us).
+                */
+               if (grow_region != 0 &&
+                   (ret = __db_rgrow(infop, grow_region)) != 0) {
+                       (void)__db_mutex_unlock(&rlp->lock, infop->fd);
+                       goto err;
+               }
 
-       /*
-        * Map the file in.  We have to do things in a strange order so that
-        * we don't get into a situation where the file was just created and
-        * isn't yet initialized.  See the comment in __db_rcreate() above.
-        *
-        * XXX
-        * We'd like to test to see if the file is too big to mmap.  Since we
-        * don't know what size or type off_t's or size_t's are, or the largest
-        * unsigned integral type is, or what random insanity the local C
-        * 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_ioinfo(name, fd, &mbytes, &bytes, NULL)) != 0) {
-               __db_err(dbenv, "%s: %s", name, strerror(ret));
-               goto err2;
-       }
-       size = mbytes * MEGABYTE + bytes;
+               /*
+                * Problem #3: when we checked the size of the file, it was
+                * still growing as part of creation.  Detected by the fact
+                * that infop->size isn't the same size as the region.
+                */
+               if (infop->size != rlp->size) {
+                       (void)__db_mutex_unlock(&rlp->lock, infop->fd);
+                       goto retry;
+               }
 
-       /* Check to make sure the first block has been written. */
-       if (size < sizeof(RLAYOUT)) {
-               ret = EAGAIN;
-               goto err2;
+               /* Increment the reference count. */
+               ++rlp->refcnt;
        }
 
-       /* Map in whatever is there. */
-       if ((ret = __db_rmap(dbenv, fd, size, &rp)) != 0)
-               goto err2;
+       /* Return the region in a locked condition. */
 
-       /*
-        * Check to make sure the region has been initialized.  We can't just
-        * grab the lock because the lock may not have been initialized yet.
-        */
-       if (rp->majver == 0) {
-               ret = EAGAIN;
-               goto err2;
-       }
-
-       /* Get the region lock. */
-       if (!LF_ISSET(DB_MUTEXDEBUG))
-               (void)__db_mutex_lock(&rp->lock, fd);
+       if (0) {
+errmsg:                __db_err(infop->dbenv, "%s: %s", infop->name, strerror(ret));
 
-       /*
-        * 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_ioinfo(name, fd, &mbytes, &bytes, NULL)) != 0) {
-               __db_err(dbenv, "%s: %s", name, strerror(ret));
-               goto err1;
-       }
-       if (size != mbytes * MEGABYTE + bytes) {
-               ret = EAGAIN;
-               goto err1;
-       }
+err:
+retry:         /* Discard the region. */
+               if (infop->addr != NULL) {
+                       (void)__db_unmapregion(infop);
+                       infop->addr = NULL;
+               }
 
-       /* The file may have just been deleted. */
-       if (F_ISSET(rp, DB_R_DELETED)) {
-               ret = EAGAIN;
-               goto err1;
-       }
+               /* Discard the backing file. */
+               if (infop->fd != -1) {
+                       (void)__db_close(infop->fd);
+                       infop->fd = -1;
 
-       /* Increment the reference count. */
-       ++rp->refcnt;
+                       if (F_ISSET(infop, REGION_CREATED))
+                               (void)__db_unlink(infop->name);
+               }
 
-       /* Release the lock. */
-       if (!LF_ISSET(DB_MUTEXDEBUG))
-               (void)__db_mutex_unlock(&rp->lock, fd);
+               /* Discard the name. */
+               if (infop->name != NULL) {
+                       FREES(infop->name);
+                       infop->name = NULL;
+               }
 
-       FREES(name);
+               /*
+                * If we had a temporary error, wait a few seconds and
+                * try again.
+                */
+               if (ret == 0) {
+                       if (++retry_cnt <= 3) {
+                               __db_sleep(retry_cnt * 2, 0);
+                               goto loop;
+                       }
+                       ret = EAGAIN;
+               }
+       }
 
-       *(void **)retp = rp;
-       return (0);
+       /*
+        * XXX
+        * HP-UX won't permit mutexes to live in anything but shared memory.
+        * Instantiate a shared region file on that architecture, regardless.
+        *
+        * XXX
+        * There's a problem in cleaning this up on application exit, or on
+        * application failure.  If an application opens a database without
+        * an environment, we create a temporary backing mpool region for it.
+        * That region is marked REGION_PRIVATE, but as HP-UX won't permit
+        * mutexes to live in anything but shared memory, we instantiate a
+        * real file plus a memory region of some form.  If the application
+        * crashes, the necessary information to delete the backing file and
+        * any system region (e.g., the shmget(2) segment ID) is no longer
+        * available.  We can't completely fix the problem, but we try.
+        *
+        * The underlying UNIX __db_mapregion() code preferentially uses the
+        * mmap(2) interface with the MAP_ANON/MAP_ANONYMOUS flags for regions
+        * that are marked REGION_PRIVATE.  This means that we normally aren't
+        * holding any system resources when we get here, in which case we can
+        * delete the backing file.  This results in a short race, from the
+        * __db_open() call above to here.
+        *
+        * If, for some reason, we are holding system resources when we get
+        * here, we don't have any choice -- we can't delete the backing file
+        * because we may need it to detach from the resources.  Set the
+        * REGION_LASTDETACH flag, so that we do all necessary cleanup when
+        * the application closes the region.
+        */
+       if (F_ISSET(infop, REGION_PRIVATE) && !F_ISSET(infop, REGION_MALLOC))
+               if (F_ISSET(infop, REGION_HOLDINGSYS))
+                       F_SET(infop, REGION_LASTDETACH);
+               else {
+                       F_SET(infop, REGION_REMOVED);
+                       F_CLR(infop, REGION_CANGROW);
+
+                       (void)__db_close(infop->fd);
+                       (void)__db_unlink(infop->name);
+               }
 
-err1:  if (!LF_ISSET(DB_MUTEXDEBUG))
-               (void)__db_mutex_unlock(&rp->lock, fd);
-err2:  if (rp != NULL)
-               (void)__db_unmap(rp, rp->size);
-       if (fd != -1)
-               (void)__db_close(fd);
-       FREES(name);
        return (ret);
 }
 
 /*
- * __db_rclose --
- *     Close a shared memory region.
+ * __db_rdetach --
+ *     De-attach from a shared memory region.
  *
- * PUBLIC: int __db_rclose __P((DB_ENV *, int, void *));
+ * PUBLIC: int __db_rdetach __P((REGINFO *));
  */
 int
-__db_rclose(dbenv, fd, ptr)
-       DB_ENV *dbenv;
-       int fd;
-       void *ptr;
+__db_rdetach(infop)
+       REGINFO *infop;
 {
-       RLAYOUT *rp;
-       int ret, t_ret;
-       const char *fail;
+       RLAYOUT *rlp;
+       int detach, ret, t_ret;
 
-       rp = ptr;
-       fail = NULL;
+       ret = 0;
 
-       /* Get the lock. */
-       if ((ret = __db_mutex_lock(&rp->lock, fd)) != 0) {
-               fail = "lock get";
-               goto err;
+       /*
+        * If the region was removed when it was created, no further action
+        * is required.
+        */
+       if (F_ISSET(infop, REGION_REMOVED))
+               goto done;
+       /*
+        * If the region was created in memory returned by malloc, the only
+        * action required is freeing the memory.
+        */
+       if (F_ISSET(infop, REGION_MALLOC)) {
+               __db_free(infop->addr);
+               goto done;
        }
 
+       /* Otherwise, attach to the region and optionally delete it. */
+       rlp = infop->addr;
+
+       /* Get the lock. */
+       (void)__db_mutex_lock(&rlp->lock, infop->fd);
+
        /* Decrement the reference count. */
-       --rp->refcnt;
+       if (rlp->refcnt == 0)
+               __db_err(infop->dbenv,
+                   "region rdetach: reference count went to zero!");
+       else
+               --rlp->refcnt;
+
+       /*
+        * If we're going to remove the region, clear the valid flag so
+        * that any region join that's blocked waiting for us will know
+        * what happened.
+        */
+       detach = 0;
+       if (F_ISSET(infop, REGION_LASTDETACH))
+               if (rlp->refcnt == 0) {
+                       detach = 1;
+                       rlp->valid = 0;
+               } else
+                       ret = EBUSY;
 
        /* Release the lock. */
-       if ((t_ret = __db_mutex_unlock(&rp->lock, fd)) != 0 && fail == NULL) {
-               ret = t_ret;
-               fail = "lock release";
-       }
+       (void)__db_mutex_unlock(&rlp->lock, infop->fd);
 
-       /* Discard the region. */
-       if ((t_ret = __db_unmap(ptr, rp->size)) != 0 && fail == NULL) {
-               ret = t_ret;
-               fail = "munmap";
-       }
+       /* Close the backing file descriptor. */
+       (void)__db_close(infop->fd);
+       infop->fd = -1;
 
-       if ((t_ret = __db_close(fd)) != 0 && fail == NULL) {
+       /* Discard our mapping of the region. */
+       if ((t_ret = __db_unmapregion(infop)) != 0 && ret == 0)
                ret = t_ret;
-               fail = "close";
+
+       /* Discard the region itself. */
+       if (detach) {
+               if ((t_ret =
+                   __db_unlinkregion(infop->name, infop) != 0) && ret == 0)
+                       ret = t_ret;
+               if ((t_ret = __db_unlink(infop->name) != 0) && ret == 0)
+                       ret = t_ret;
        }
 
-       if (fail == NULL)
-               return (0);
+done:  /* Discard the name. */
+       if (infop->name != NULL) {
+               FREES(infop->name);
+               infop->name = NULL;
+       }
 
-err:   __db_err(dbenv, "region detach: %s: %s", fail, strerror(ret));
        return (ret);
 }
 
 /*
  * __db_runlink --
- *     Remove a shared memory region.
+ *     Remove a region.
  *
- * PUBLIC: int __db_runlink __P((DB_ENV *,
- * PUBLIC:    APPNAME, const char *, const char *, int));
+ * PUBLIC: int __db_runlink __P((REGINFO *, int));
  */
 int
-__db_runlink(dbenv, appname, path, file, force)
-       DB_ENV *dbenv;
-       APPNAME appname;
-       const char *path, *file;
+__db_runlink(infop, force)
+       REGINFO *infop;
        int force;
 {
-       RLAYOUT *rp;
-       int cnt, fd, ret, t_ret;
+       RLAYOUT rl, *rlp;
+       size_t size;
+       ssize_t nr;
+       u_int32_t mbytes, bytes;
+       int fd, ret, t_ret;
        char *name;
 
-       rp = NULL;
+       /*
+        * XXX
+        * We assume that we've created a new REGINFO structure for this
+        * call, not used one that was already initialized.  Regardless,
+        * if anyone is planning to use it after we're done, they're going
+        * to be sorely disappointed.
+        *
+        * If force isn't set, we attach to the region, set a flag to delete
+        * the region on last close, and let the region delete code do the
+        * work.
+        */
+       if (!force) {
+               if ((ret = __db_rattach(infop)) != 0)
+                       return (ret);
 
-       /* Get the filename. */
-       if ((ret = __db_appname(dbenv, appname, path, file, NULL, &name)) != 0)
-               return (ret);
+               rlp = (RLAYOUT *)infop->addr;
+               (void)__db_mutex_unlock(&rlp->lock, infop->fd);
 
-       /* If the file doesn't exist, we're done. */
-       if (__db_exists(name, NULL))
-               goto done;
+               F_SET(infop, REGION_LASTDETACH);
+
+               return (__db_rdetach(infop));
+       }
 
        /*
-        * If we're called with a force flag, try and unlink the file.  This
-        * may not succeed if the file is currently open, but there's nothing
-        * we can do about that.  There is a race condition between the check
-        * for existence above and the actual unlink.  If someone else snuck
-        * in and removed it before we do the remove, then we might get an
-        * ENOENT error.  If we get the ENOENT, we treat it as success, just
-        * as we do above.
+        * Otherwise, we don't want to attach to the region.  We may have been
+        * called to clean up if a process died leaving a region locked and/or
+        * corrupted, which could cause the attach to hang.
         */
-       if (force) {
-               if ((ret = __db_unlink(name)) != 0 && ret != ENOENT)
-                       goto err1;
-               goto done;
+       if ((ret = __db_appname(infop->dbenv, infop->appname,
+           infop->path, infop->file, infop->dbflags, NULL, &name)) != 0)
+               return (ret);
+
+       /*
+        * An underlying file is created for all regions other than private
+        * (REGION_PRIVATE) ones, regardless of whether or not it's used to
+        * back the region.  If that file doesn't exist, we're done.
+        */
+       if (__db_exists(name, NULL) != 0) {
+               FREES(name);
+               return (0);
        }
 
-       /* 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);
+       /*
+        * See the comments in __db_rattach -- figure out if this is a regular
+        * file backing a region or if it's a regular file with information
+        * about a region.
+        */
+       if ((ret = __db_open(name, DB_RDONLY, DB_RDONLY, 0, &fd)) != 0)
+               goto errmsg;
+       if ((ret = __db_ioinfo(name, fd, &mbytes, &bytes, NULL)) != 0)
+               goto errmsg;
+       size = mbytes * MEGABYTE + bytes;
 
-       /* If the region is currently being deleted, fail. */
-       if (F_ISSET(rp, DB_R_DELETED)) {
-               ret = ENOENT;           /* XXX: ENOENT? */
-               goto err2;
-       }
+       if (size <= sizeof(RLAYOUT)) {
+               if ((ret = __db_read(fd, &rl, sizeof(rl), &nr)) != 0)
+                       goto errmsg;
+               if (rl.valid != DB_REGIONMAGIC) {
+                       __db_err(infop->dbenv,
+                           "%s: illegal region magic number", name);
+                       ret = EINVAL;
+                       goto err;
+               }
 
-       /* If the region is currently in use by someone else, fail. */
-       if (rp->refcnt > 1) {
-               ret = EBUSY;
-               goto err2;
+               /* Set the size, memory id and characteristics. */
+               infop->size = rl.size;
+               infop->segid = rl.segid;
+               if (F_ISSET(&rl, REGION_ANONYMOUS))
+                       F_SET(infop, REGION_ANONYMOUS);
+       } else {
+               infop->size = size;
+               infop->segid = INVALID_SEGID;
        }
 
-       /* Set the delete flag. */
-       F_SET(rp, DB_R_DELETED);
-
-       /* Release the lock and close the region. */
-       (void)__db_mutex_unlock(&rp->lock, fd);
-       if ((t_ret = __db_rclose(dbenv, fd, rp)) != 0 && ret == 0)
-               goto err1;
+       /* Remove the underlying region. */
+       ret = __db_unlinkregion(name, infop);
 
        /*
-        * Unlink the region.  There's a race here -- other threads or
-        * processes might be opening the region while we're trying to
-        * remove it.  They'll fail, because we've set the DELETED flag,
-        * but they could still stop us from succeeding in the unlink.
+        * Unlink the backing file.  Close the open file descriptor first,
+        * because some architectures (e.g., Win32) won't unlink a file if
+        * open file descriptors remain.
         */
-       for (cnt = 5; cnt > 0; --cnt) {
-               if ((ret = __db_unlink(name)) == 0)
-                       break;
-               (void)__db_sleep(0, 250000);
-       }
-       if (ret == 0) {
-done:          FREES(name);
-               return (0);
-       }
-
-       /* 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);
-       F_CLR(rp, DB_R_DELETED);
-       /* FALLTHROUGH */
+       (void)__db_close(fd);
+       if ((t_ret = __db_unlink(name)) != 0 && ret == 0)
+               ret = t_ret;
 
-err2:  (void)__db_mutex_unlock(&rp->lock, fd);
-       (void)__db_rclose(dbenv, fd, rp);
-err1:  __db_err(dbenv, "region unlink: %s: %s", name, strerror(ret));
+       if (0) {
+errmsg:                __db_err(infop->dbenv, "%s: %s", name, strerror(ret));
+err:           (void)__db_close(fd);
+       }
 
        FREES(name);
        return (ret);
 }
 
 /*
- * DB creates all regions on 4K boundaries so that we don't make the
- * underlying VM unhappy.
- */
-#define        __DB_VMPAGESIZE (4 * 1024)
-
-/*
  * __db_rgrow --
- *     Extend a region by a specified amount.
+ *     Extend a region.
  *
- * PUBLIC: int __db_rgrow __P((DB_ENV *, int, size_t));
+ * PUBLIC: int __db_rgrow __P((REGINFO *, size_t));
  */
 int
-__db_rgrow(dbenv, fd, incr)
-       DB_ENV *dbenv;
-       int fd;
-       size_t incr;
+__db_rgrow(infop, new_size)
+       REGINFO *infop;
+       size_t new_size;
+{
+       RLAYOUT *rlp;
+       size_t increment;
+       int ret;
+
+       /*
+        * !!!
+        * This routine MUST be called with the region already locked.
+        */
+
+       /* The underlying routines have flagged if this region can grow. */
+       if (!F_ISSET(infop, REGION_CANGROW))
+               return (EINVAL);
+
+       /*
+        * Round off the requested size to the next page boundary, and
+        * determine the additional space required.
+        */
+       rlp = (RLAYOUT *)infop->addr;
+       DB_ROUNDOFF(new_size);
+       increment = new_size - rlp->size;
+
+       if ((ret = __db_growregion(infop, increment)) != 0)
+               return (ret);
+
+       /* Update the on-disk region size. */
+       rlp->size = new_size;
+
+       /* Detach from and reattach to the region. */
+       return (__db_rreattach(infop, new_size));
+}
+
+/*
+ * __db_growregion --
+ *     Grow a shared memory region.
+ */
+static int
+__db_growregion(infop, increment)
+       REGINFO *infop;
+       size_t increment;
 {
+       db_pgno_t pages;
        size_t i;
-       ssize_t nw;
-       int mmap_init_needed, ret;
-       char buf[__DB_VMPAGESIZE];
+       ssize_t nr, nw;
+       u_int32_t relative;
+       int ret;
+       char buf[DB_VMPAGESIZE];
 
        /* Seek to the end of the region. */
-       if ((ret = __db_seek(fd, 0, 0, 0, SEEK_END)) != 0)
+       if ((ret = __db_seek(infop->fd, 0, 0, 0, 0, SEEK_END)) != 0)
                goto err;
 
        /* Write nuls to the new bytes. */
        memset(buf, 0, sizeof(buf));
 
        /*
-        * Historically, some systems required that all of the bytes of the
-        * region be written before it could be mmapped and accessed randomly.
-        *
-        * Windows/95 doesn't have that problem, but it leaves file contents
-        * uninitialized.  Win/NT apparently initializes them.
+        * Some systems require that all of the bytes of the region be
+        * written before it can be mapped and accessed randomly, and
+        * other systems don't zero out the pages.
         */
-#ifdef MMAP_INIT_NEEDED
-       mmap_init_needed = 1;
-#else
-       mmap_init_needed = __os_oldwin();
-#endif
-       if (mmap_init_needed)
+       if (__db_mapinit())
                /* Extend the region by writing each new page. */
-               for (i = 0; i < incr; i += __DB_VMPAGESIZE) {
-                       if ((ret = __db_write(fd, buf, sizeof(buf), &nw)) != 0)
+               for (i = 0; i < increment; i += DB_VMPAGESIZE) {
+                       if ((ret =
+                           __db_write(infop->fd, buf, sizeof(buf), &nw)) != 0)
                                goto err;
                        if (nw != sizeof(buf))
                                goto eio;
                }
        else {
                /*
-                * Extend the region by writing the last page.
-                *
-                * Round off the increment to the next page boundary.
+                * Extend the region by writing the last page.  If the region
+                * is >4Gb, increment may be larger than the maximum possible
+                * seek "relative" argument, as it's an unsigned 32-bit value.
+                * Break the offset into pages of 1MB each so that we don't
+                * overflow (2^20 + 2^32 is bigger than any memory I expect
+                * to see for awhile).
                 */
-               incr += __DB_VMPAGESIZE - 1;
-               incr -= incr % __DB_VMPAGESIZE;
-
-               /* Write the last page, not the page after the last. */
-               if ((ret =
-                   __db_seek(fd, 0, 0, incr - __DB_VMPAGESIZE, SEEK_CUR)) != 0)
+               pages = (increment - DB_VMPAGESIZE) / MEGABYTE;
+               relative = (increment - DB_VMPAGESIZE) % MEGABYTE;
+               if ((ret = __db_seek(infop->fd,
+                   MEGABYTE, pages, relative, 0, SEEK_CUR)) != 0)
                        goto err;
-               if ((ret = __db_write(fd, buf, sizeof(buf), &nw)) != 0)
+               if ((ret = __db_write(infop->fd, buf, sizeof(buf), &nw)) != 0)
                        goto err;
                if (nw != sizeof(buf))
                        goto eio;
+
+               /*
+                * It's sometimes significantly faster to page-fault in all
+                * of the region's pages before we run the application, as
+                * we can see fairly nasty side-effects when we page-fault
+                * while holding various locks, i.e., the lock takes a long
+                * time, and other threads convoy behind the lock holder.
+                */
+               if (DB_GLOBAL(db_region_init)) {
+                       pages = increment / MEGABYTE;
+                       relative = increment % MEGABYTE;
+                       if ((ret = __db_seek(infop->fd,
+                           MEGABYTE, pages, relative, 1, SEEK_END)) != 0)
+                               goto err;
+
+                       /* Read a byte from each page. */
+                       for (i = 0; i < increment; i += DB_VMPAGESIZE) {
+                               if ((ret =
+                                   __db_read(infop->fd, buf, 1, &nr)) != 0)
+                                       goto err;
+                               if (nr != 1)
+                                       goto eio;
+                               if ((ret = __db_seek(infop->fd,
+                                   0, 0, DB_VMPAGESIZE - 1, 0, SEEK_CUR)) != 0)
+                                       goto err;
+                       }
+               }
        }
        return (0);
 
 eio:   ret = EIO;
-err:   __db_err(dbenv, "region grow: %s", strerror(ret));
+err:   __db_err(infop->dbenv, "region grow: %s", strerror(ret));
        return (ret);
 }
 
 /*
- * __db_rremap --
- *     Unmap the old region and map in a new region of a new size.  If
- *     either call fails, returns NULL, else returns the address of the
- *     new region.
+ * __db_rreattach --
+ *     Detach from and reattach to a region.
  *
- * PUBLIC: int __db_rremap __P((DB_ENV *, void *, size_t, size_t, int, void *));
+ * PUBLIC: int __db_rreattach __P((REGINFO *, size_t));
  */
 int
-__db_rremap(dbenv, ptr, oldsize, newsize, fd, retp)
-       DB_ENV *dbenv;
-       void *ptr, *retp;
-       size_t oldsize, newsize;
-       int fd;
+__db_rreattach(infop, new_size)
+       REGINFO *infop;
+       size_t new_size;
 {
        int ret;
 
-       if ((ret = __db_unmap(ptr, oldsize)) != 0) {
-               __db_err(dbenv, "region remap: munmap: %s", strerror(ret));
-               return (ret);
+#ifdef DIAGNOSTIC
+       if (infop->name == NULL) {
+               __db_err(infop->dbenv, "__db_rreattach: name was NULL");
+               return (EINVAL);
        }
+#endif
+       /*
+        * If we're growing an already mapped region, we have to unmap it
+        * and get it back.  We have it locked, so nobody else can get in,
+        * which makes it fairly straight-forward to do, as everybody else
+        * is going to block while we do the unmap/remap.  NB: if we fail
+        * to get it back, the pooch is genuinely screwed, because we can
+        * never release the lock we're holding.
+        *
+        * Detach from the region.  We have to do this first so architectures
+        * that don't permit a file to be mapped into different places in the
+        * address space simultaneously, e.g., HP's PaRisc, will work.
+        */
+       if ((ret = __db_unmapregion(infop)) != 0)
+               return (ret);
 
-       return (__db_rmap(dbenv, fd, newsize, retp));
-}
-
-/*
- * __db_rmap --
- *     Attach to a shared memory region.
- */
-static int
-__db_rmap(dbenv, fd, size, retp)
-       DB_ENV *dbenv;
-       int fd;
-       size_t size;
-       void *retp;
-{
-       RLAYOUT *rp;
-       int ret;
+       /* Update the caller's REGINFO size to the new map size. */
+       infop->size = new_size;
 
-       if ((ret = __db_map(fd, size, 0, 0, (void **)&rp)) != 0) {
-               __db_err(dbenv, "region map: mmap %s", strerror(ret));
-               return (ret);
-       }
-       if (rp->size < size)
-               rp->size = size;
+       /* Attach to the region. */
+       ret = __db_mapregion(infop->name, infop);
 
-       *(void **)retp = rp;
-       return (0);
+       return (ret);
 }
index f0202dd..0fa696b 100644 (file)
@@ -1,21 +1,21 @@
 /*-
  * See the file LICENSE for redistribution information.
  *
- * Copyright (c) 1996, 1997
+ * Copyright (c) 1996, 1997, 1998
  *     Sleepycat Software.  All rights reserved.
  */
 
 #include "config.h"
 
 #ifndef lint
-static const char sccsid[] = "@(#)db_salloc.c  10.6 (Sleepycat) 7/5/97";
+static const char sccsid[] = "@(#)db_salloc.c  10.13 (Sleepycat) 5/10/98";
 #endif /* not lint */
 
 #ifndef NO_SYSTEM_INCLUDES
 #include <sys/types.h>
 
 #include <errno.h>
-#include <stdio.h>
+#include <string.h>
 #endif
 
 #include "db_int.h"
@@ -109,11 +109,13 @@ __db_shalloc(p, len, align, retp)
 
                *(void **)retp = rp;
 
+#define        SHALLOC_FRAGMENT        32
                /*
-                * If there are at least 32 bytes of additional memory, divide
-                * the chunk into two chunks.
+                * If there are at least SHALLOC_FRAGMENT additional bytes of
+                * memory, divide the chunk into two chunks.
                 */
-               if ((u_int8_t *)rp >= (u_int8_t *)&elp->links + 32) {
+               if ((u_int8_t *)rp >=
+                   (u_int8_t *)&elp->links + SHALLOC_FRAGMENT) {
                        sp = rp;
                        *--sp = elp->len -
                            ((u_int8_t *)rp - (u_int8_t *)&elp->links);
@@ -136,7 +138,7 @@ __db_shalloc(p, len, align, retp)
                return (0);
        }
 
-       /* Nothing found large enough; need to figure out how to grow region. */
+       /* Nothing found large enough; need to grow the region. */
        return (ENOMEM);
 }
 
@@ -159,12 +161,18 @@ __db_shalloc_free(regionp, ptr)
         * Step back over flagged length fields to find the beginning of
         * the object and its real size.
         */
-       for (sp = (size_t *)ptr; sp[-1] == ILLEGAL_SIZE; --sp);
+       for (sp = (size_t *)ptr; sp[-1] == ILLEGAL_SIZE; --sp)
+               ;
        ptr = sp;
 
        newp = (struct __data *)((u_int8_t *)ptr - sizeof(size_t));
        free_size = newp->len;
 
+       /* Trash the returned memory. */
+#ifdef DIAGNOSTIC
+       memset(ptr, 0xff, free_size);
+#endif
+
        /*
         * Walk the list, looking for where this entry goes.
         *
@@ -177,7 +185,8 @@ __db_shalloc_free(regionp, ptr)
        hp = (struct __head *)regionp;
        for (elp = SH_LIST_FIRST(hp, __data), lastp = NULL;
            elp != NULL && (void *)elp < (void *)ptr;
-           lastp = elp, elp = SH_LIST_NEXT(elp, links, __data));
+           lastp = elp, elp = SH_LIST_NEXT(elp, links, __data))
+               ;
 
        /*
         * Elp is either NULL (we reached the end of the list), or the slot
@@ -259,32 +268,34 @@ __db_shsizeof(ptr)
         * Step back over flagged length fields to find the beginning of
         * the object and its real size.
         */
-       for (sp = (size_t *)ptr; sp[-1] == ILLEGAL_SIZE; --sp);
+       for (sp = (size_t *)ptr; sp[-1] == ILLEGAL_SIZE; --sp)
+               ;
 
        elp = (struct __data *)((u_int8_t *)sp - sizeof(size_t));
        return (elp->len);
 }
 
-#ifdef DEBUG
 /*
  * __db_shalloc_dump --
  *
- * PUBLIC: void __db_shalloc_dump __P((FILE *, void *));
+ * PUBLIC: void __db_shalloc_dump __P((void *, FILE *));
  */
 void
-__db_shalloc_dump(fp, addr)
-       FILE *fp;
+__db_shalloc_dump(addr, fp)
        void *addr;
+       FILE *fp;
 {
        struct __data *elp;
 
+       /* Make it easy to call from the debugger. */
        if (fp == NULL)
                fp = stderr;
 
+       fprintf(fp, "%s\nMemory free list\n", DB_LINE);
+
        for (elp = SH_LIST_FIRST((struct __head *)addr, __data);
            elp != NULL;
            elp = SH_LIST_NEXT(elp, links, __data))
                fprintf(fp, "%#lx: %lu\t", (u_long)elp, (u_long)elp->len);
        fprintf(fp, "\n");
 }
-#endif
index ab188f5..3f48a55 100644 (file)
@@ -1,14 +1,14 @@
 /*-
  * See the file LICENSE for redistribution information.
  *
- * Copyright (c) 1996, 1997
+ * Copyright (c) 1996, 1997, 1998
  *     Sleepycat Software.  All rights reserved.
  */
 
 #include "config.h"
 
 #ifndef lint
-static const char sccsid[] = "@(#)db_shash.c   10.4 (Sleepycat) 1/8/98";
+static const char sccsid[] = "@(#)db_shash.c   10.9 (Sleepycat) 4/10/98";
 #endif /* not lint */
 
 #ifndef NO_SYSTEM_INCLUDES
@@ -19,39 +19,75 @@ static const char sccsid[] = "@(#)db_shash.c        10.4 (Sleepycat) 1/8/98";
 #include "shqueue.h"
 #include "common_ext.h"
 
-/* Powers-of-2 and close-by prime number pairs. */
+/*
+ * Table of good hash values.  Up to ~250,000 buckets, we use powers of 2.
+ * After that, we slow the rate of increase by half.  For each choice, we
+ * then use a nearby prime number as the hash value.
+ *
+ * If a terabyte is the maximum cache we'll see, and we assume there are
+ * 10 1K buckets on each hash chain, then 107374182 is the maximum number
+ * of buckets we'll ever need.
+ */
 static const struct {
-       u_int   power;
-       u_int   prime;
+       u_int32_t power;
+       u_int32_t prime;
 } list[] = {
-       {  64,    67},
-       { 128,   131},
-       { 256,   257},
-       { 512,   521},
-       {1024,  1031},
-       {2048,  2053},
-       {4096,  4099},
-       {8192,  8191},
-       {0,        0}
+       {        64,            67},            /* 2^6 */
+       {       128,           131},            /* 2^7 */
+       {       256,           257},            /* 2^8 */
+       {       512,           521},            /* 2^9 */
+       {      1024,          1031},            /* 2^10 */
+       {      2048,          2053},            /* 2^11 */
+       {      4096,          4099},            /* 2^12 */
+       {      8192,          8191},            /* 2^13 */
+       {     16384,         16381},            /* 2^14 */
+       {     32768,         32771},            /* 2^15 */
+       {     65536,         65537},            /* 2^16 */
+       {    131072,        131071},            /* 2^17 */
+       {    262144,        262147},            /* 2^18 */
+       {    393216,        393209},            /* 2^18 + 2^18/2 */
+       {    524288,        524287},            /* 2^19 */
+       {    786432,        786431},            /* 2^19 + 2^19/2 */
+       {   1048576,       1048573},            /* 2^20 */
+       {   1572864,       1572869},            /* 2^20 + 2^20/2 */
+       {   2097152,       2097169},            /* 2^21 */
+       {   3145728,       3145721},            /* 2^21 + 2^21/2 */
+       {   4194304,       4194301},            /* 2^22 */
+       {   6291456,       6291449},            /* 2^22 + 2^22/2 */
+       {   8388608,       8388617},            /* 2^23 */
+       {  12582912,      12582917},            /* 2^23 + 2^23/2 */
+       {  16777216,      16777213},            /* 2^24 */
+       {  25165824,      25165813},            /* 2^24 + 2^24/2 */
+       {  33554432,      33554393},            /* 2^25 */
+       {  50331648,      50331653},            /* 2^25 + 2^25/2 */
+       {  67108864,      67108859},            /* 2^26 */
+       { 100663296,     100663291},            /* 2^26 + 2^26/2 */
+       { 134217728,     134217757},            /* 2^27 */
+       { 201326592,     201326611},            /* 2^27 + 2^27/2 */
+       { 268435456,     268435459},            /* 2^28 */
+       { 402653184,     402653189},            /* 2^28 + 2^28/2 */
+       { 536870912,     536870909},            /* 2^29 */
+       { 805306368,     805306357},            /* 2^29 + 2^29/2 */
+       {1073741824,    1073741827},            /* 2^30 */
+       {0,             0}
 };
 
 /*
  * __db_tablesize --
  *     Choose a size for the hash table.
  *
- * PUBLIC: int __db_tablesize __P((u_int));
+ * PUBLIC: int __db_tablesize __P((u_int32_t));
  */
 int
 __db_tablesize(n_buckets)
-       u_int n_buckets;
+       u_int32_t n_buckets;
 {
        int i;
 
        /*
-        * We try to be clever about how big we make the hash tables.  Pick
-        * a prime number close to the "suggested" number of elements that
-        * will be in the hash table.  We shoot for minimum collisions (i.e.
-        * one element in each bucket).  We use 64 as the minimum table size.
+        * We try to be clever about how big we make the hash tables.  Use a
+        * prime number close to the "suggested" number of elements that will
+        * be in the hash table.  Use 64 as the minimum hash table size.
         *
         * Ref: Sedgewick, Algorithms in C, "Hash Functions"
         */
@@ -73,14 +109,14 @@ __db_tablesize(n_buckets)
  * __db_hashinit --
  *     Initialize a hash table that resides in shared memory.
  *
- * PUBLIC: void __db_hashinit __P((void *, int));
+ * PUBLIC: void __db_hashinit __P((void *, u_int32_t));
  */
 void
 __db_hashinit(begin, nelements)
        void *begin;
-       int nelements;
+       u_int32_t nelements;
 {
-       int i;
+       u_int32_t i;
        SH_TAILQ_HEAD(hash_head) *headp;
 
        headp = (struct hash_head *)begin;
index 7f784a0..e5e1058 100644 (file)
@@ -24,6 +24,9 @@
 /* Define to `unsigned' if <sys/types.h> doesn't define.  */
 /* #undef size_t */
 
+/* Define if the `S_IS*' macros in <sys/stat.h> do not work properly.  */
+/* #undef STAT_MACROS_BROKEN */
+
 /* Define if you have the ANSI C header files.  */
 #define STDC_HEADERS 1
 
 /* Define if you want a debugging version. */
 /* #undef DEBUG */
 
+/* Define if you want a version with run-time diagnostic checking. */
+/* #undef DIAGNOSTIC */
+
 /* Define if you have sigfillset (and sigprocmask). */
 #define HAVE_SIGFILLSET 1
 
-/* Define if seeking to 64-bit file offsets requires the _llseek() call. */
-/* #undef HAVE_LLSEEK */
-
-/* Define if seeking to 64-bit file offsets requires the _lseeki64() call. */
-/* #undef HAVE_LSEEKI */
+/* Define if building on AIX, HP, Solaris to get big-file environment. */
+/* #undef HAVE_FILE_OFFSET_BITS */
+#ifdef HAVE_FILE_OFFSET_BITS
+#define _FILE_OFFSET_BITS 64
+#endif
 
 /* Define if you have spinlocks. */
 /* #undef HAVE_SPINLOCKS */
 /* Define if you want to use mc68020/gcc assembly spinlocks. */
 /* #undef HAVE_ASSEM_MC68020_GCC */
 
+/* Define if you want to use parisc/gcc assembly spinlocks. */
+/* #undef HAVE_ASSEM_PARISC_GCC */
+
+/* Define if you want to use sco/cc assembly spinlocks. */
+/* #undef HAVE_ASSEM_SCO_CC */
+
 /* Define if you want to use sparc/gcc assembly spinlocks. */
 /* #undef HAVE_ASSEM_SPARC_GCC */
 
@@ -69,6 +81,9 @@
 /* Define if you have the SGI abilock_t spinlocks. */
 /* #undef HAVE_FUNC_SGI */
 
+/* Define if you have the ReliantUNIX spinlock_t spinlocks. */
+/* #undef HAVE_FUNC_RELIANT */
+
 /* Define if you have the Solaris mutex_t spinlocks. */
 /* #undef HAVE_FUNC_SOLARIS */
 
 /* Define if you have the select function.  */
 #define HAVE_SELECT 1
 
+/* Define if you have the shmget function.  */
+#define HAVE_SHMGET 1
+
 /* Define if you have the snprintf function.  */
 #define HAVE_SNPRINTF 1
 
-/* Define if you have the strdup function.  */
-#define HAVE_STRDUP 1
-
 /* Define if you have the strerror function.  */
 #define HAVE_STRERROR 1
 
index 6a75bcd..e1f5c72 100644 (file)
--- a/db2/db.h
+++ b/db2/db.h
@@ -1,10 +1,10 @@
 /*-
  * See the file LICENSE for redistribution information.
  *
- * Copyright (c) 1996, 1997
+ * Copyright (c) 1996, 1997, 1998
  *     Sleepycat Software.  All rights reserved.
  *
- *     @(#)db.h.src    10.102 (Sleepycat) 1/18/98
+ *     @(#)db.h.src    10.131 (Sleepycat) 6/2/98
  */
 
 #ifndef _DB_H_
@@ -54,8 +54,7 @@
  *
  * !!!
  * We also provide the standard u_int, u_long etc., if they're not provided
- * by the system.  This isn't completely necessary, but the example programs
- * need them.
+ * by the system.
  */
 #ifndef        __BIT_TYPES_DEFINED__
 #define        __BIT_TYPES_DEFINED__
@@ -72,9 +71,9 @@
 
 
 #define        DB_VERSION_MAJOR        2
-#define        DB_VERSION_MINOR        3
-#define        DB_VERSION_PATCH        16
-#define        DB_VERSION_STRING       "Sleepycat Software: DB 2.3.16: (1/19/98)"
+#define        DB_VERSION_MINOR        4
+#define        DB_VERSION_PATCH        14
+#define        DB_VERSION_STRING       "Sleepycat Software: DB 2.4.14: (6/2/98)"
 
 typedef        u_int32_t       db_pgno_t;      /* Page number type. */
 typedef        u_int16_t       db_indx_t;      /* Page offset type. */
@@ -95,6 +94,7 @@ struct __db_bt_stat;  typedef struct __db_bt_stat DB_BTREE_STAT;
 struct __db_dbt;       typedef struct __db_dbt DBT;
 struct __db_env;       typedef struct __db_env DB_ENV;
 struct __db_info;      typedef struct __db_info DB_INFO;
+struct __db_lock_stat; typedef struct __db_lock_stat DB_LOCK_STAT;
 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;
@@ -102,6 +102,7 @@ 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_finfo;typedef struct __db_mpool_finfo DB_MPOOL_FINFO;
 struct __db_mpool_fstat;typedef struct __db_mpool_fstat DB_MPOOL_FSTAT;
 struct __db_mpool_stat;        typedef struct __db_mpool_stat DB_MPOOL_STAT;
 struct __db_mpoolfile; typedef struct __db_mpoolfile DB_MPOOLFILE;
@@ -134,7 +135,7 @@ struct __db_dbt {
  * There are a set of functions that the application can replace with its
  * own versions, and some other knobs which can be turned at run-time.
  */
-#define        DB_FUNC_CALLOC   1              /* ANSI C calloc. */
+#define        DB_FUNC_CALLOC   1      /* DELETED: 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. */
@@ -149,12 +150,18 @@ struct __db_dbt {
 #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              /* DB: strdup(3). */
+#define        DB_FUNC_STRDUP  16      /* DELETED: DB: strdup(3). */
 #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. */
 #define        DB_TSL_SPINS    21              /* DB: initialize spin count. */
+#define        DB_FUNC_RUNLINK 22              /* DB: remove a shared region. */
+#define        DB_REGION_ANON  23              /* DB: anonymous, unnamed regions. */
+#define        DB_REGION_INIT  24              /* DB: page-fault regions in create. */
+#define        DB_REGION_NAME  25              /* DB: anonymous, named regions. */
+#define        DB_MUTEXLOCKS   26              /* DB: turn off all mutex locks. */
+#define        DB_PAGEYIELD    27              /* DB: yield the CPU on pool get. */
 
 /*
  * Database configuration and initialization.
@@ -162,52 +169,51 @@ struct __db_dbt {
  /*
   * Flags understood by both db_open(3) and db_appinit(3).
   */
-#define        DB_CREATE               0x00001 /* O_CREAT: create file as necessary. */
-#define        DB_NOMMAP               0x00002 /* Don't mmap underlying file. */
-#define        DB_THREAD               0x00004 /* Free-thread DB package handles. */
+#define        DB_CREATE             0x000001  /* O_CREAT: create file as necessary. */
+#define        DB_NOMMAP             0x000002  /* Don't mmap underlying file. */
+#define        DB_THREAD             0x000004  /* Free-thread DB package handles. */
 
 /*
  * Flags understood by db_appinit(3).
- *
- * DB_MUTEXDEBUG is internal only, and not documented.
  */
-/*                             0x00007    COMMON MASK. */
-#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. */
+/*                           0x000007     COMMON MASK. */
+#define        DB_INIT_LOCK          0x000008  /* Initialize locking. */
+#define        DB_INIT_LOG           0x000010  /* Initialize logging. */
+#define        DB_INIT_MPOOL         0x000020  /* Initialize mpool. */
+#define        DB_INIT_TXN           0x000040  /* Initialize transactions. */
+#define        DB_MPOOL_PRIVATE      0x000080  /* Mpool: private memory pool. */
+#define        __UNUSED_100          0x000100
+#define        DB_RECOVER            0x000200  /* Run normal recovery. */
+#define        DB_RECOVER_FATAL      0x000400  /* Run catastrophic recovery. */
+#define        DB_TXN_NOSYNC         0x000800  /* Do not sync log on commit. */
+#define        DB_USE_ENVIRON        0x001000  /* Use the environment. */
+#define        DB_USE_ENVIRON_ROOT   0x002000  /* Use the environment if root. */
 
 /* CURRENTLY UNUSED LOCK FLAGS. */
-#define        DB_TXN_LOCK_2PL         0x00000 /* Two-phase locking. */
-#define        DB_TXN_LOCK_OPTIMISTIC  0x00000 /* Optimistic locking. */
-#define        DB_TXN_LOCK_MASK        0x00000 /* Lock flags mask. */
+#define        DB_TXN_LOCK_2PL       0x000000  /* Two-phase locking. */
+#define        DB_TXN_LOCK_OPTIMIST  0x000000  /* Optimistic locking. */
+#define        DB_TXN_LOCK_MASK      0x000000  /* Lock flags mask. */
 
 /* CURRENTLY UNUSED LOG FLAGS. */
-#define        DB_TXN_LOG_REDO         0x00000 /* Redo-only logging. */
-#define        DB_TXN_LOG_UNDO         0x00000 /* Undo-only logging. */
-#define        DB_TXN_LOG_UNDOREDO     0x00000 /* Undo/redo write-ahead logging. */
-#define        DB_TXN_LOG_MASK         0x00000 /* Log flags mask. */
+#define        DB_TXN_LOG_REDO       0x000000  /* Redo-only logging. */
+#define        DB_TXN_LOG_UNDO       0x000000  /* Undo-only logging. */
+#define        DB_TXN_LOG_UNDOREDO   0x000000  /* Undo/redo write-ahead logging. */
+#define        DB_TXN_LOG_MASK       0x000000  /* Log flags mask. */
 
 /*
  * Flags understood by db_open(3).
  *
- * DB_EXCL and DB_TEMPORARY are internal only, and not documented.
- * DB_SEQUENTIAL is currently internal, but likely to be exported some day.
+ * DB_EXCL and DB_TEMPORARY are internal only, and are not documented.
+ * DB_SEQUENTIAL is currently internal, but may be exported some day.
  */
-/*                             0x00007    COMMON MASK. */
-/*                             0x07fff    ALREADY USED. */
-#define        DB_EXCL                 0x08000 /* O_EXCL: exclusive open. */
-#define        DB_RDONLY               0x10000 /* O_RDONLY: read-only. */
-#define        DB_SEQUENTIAL           0x20000 /* Indicate sequential access. */
-#define        DB_TEMPORARY            0x40000 /* Remove on last close. */
-#define        DB_TRUNCATE             0x80000 /* O_TRUNCATE: replace existing DB. */
+/*                           0x000007     COMMON MASK. */
+/*                           0x003fff     ALREADY USED. */
+#define        __UNUSED_4000         0x004000
+#define        DB_EXCL               0x008000  /* O_EXCL: exclusive open. */
+#define        DB_RDONLY             0x010000  /* O_RDONLY: read-only. */
+#define        DB_SEQUENTIAL         0x020000  /* Indicate sequential access. */
+#define        DB_TEMPORARY          0x040000  /* Remove on last close. */
+#define        DB_TRUNCATE           0x080000  /* O_TRUNCATE: replace existing DB. */
 
 /*
  * Deadlock detector modes; used in the DBENV structure to configure the
@@ -240,9 +246,9 @@ struct __db_env {
        /* Locking. */
        DB_LOCKTAB      *lk_info;       /* Return from lock_open(). */
        u_int8_t        *lk_conflicts;  /* Two dimensional conflict matrix. */
-       int              lk_modes;      /* Number of lock modes in table. */
-       u_int            lk_max;        /* Maximum number of locks. */
-       u_int32_t        lk_detect;     /* Deadlock detect on every conflict. */
+       u_int32_t        lk_modes;      /* Number of lock modes in table. */
+       u_int32_t        lk_max;        /* Maximum number of locks. */
+       u_int32_t        lk_detect;     /* Deadlock detect on all conflicts. */
 
        /* Logging. */
        DB_LOG          *lg_info;       /* Return from log_open(). */
@@ -255,7 +261,7 @@ struct __db_env {
 
        /* Transactions. */
        DB_TXNMGR       *tx_info;       /* Return from txn_open(). */
-       unsigned int     tx_max;        /* Maximum number of transactions. */
+       u_int32_t        tx_max;        /* Maximum number of transactions. */
        int (*tx_recover)               /* Dispatch function for recovery. */
            __P((DB_LOG *, DBT *, DB_LSN *, int, void *));
 
@@ -300,17 +306,17 @@ struct __db_info {
        void *(*db_malloc) __P((size_t));
 
        /* Btree access method. */
-       int              bt_maxkey;     /* Maximum keys per page. */
-       int              bt_minkey;     /* Minimum keys per page. */
+       u_int32_t        bt_maxkey;     /* Maximum keys per page. */
+       u_int32_t        bt_minkey;     /* Minimum keys per page. */
        int (*bt_compare)               /* Comparison function. */
            __P((const DBT *, const DBT *));
        size_t (*bt_prefix)             /* Prefix function. */
            __P((const DBT *, const DBT *));
 
        /* Hash access method. */
-       unsigned int     h_ffactor;     /* Fill factor. */
-       unsigned int     h_nelem;       /* Number of elements. */
-       u_int32_t       (*h_hash)       /* Hash function. */
+       u_int32_t        h_ffactor;     /* Fill factor. */
+       u_int32_t        h_nelem;       /* Number of elements. */
+       u_int32_t      (*h_hash)        /* Hash function. */
            __P((const void *, u_int32_t));
 
        /* Recno access method. */
@@ -353,6 +359,7 @@ struct __db_info {
 #define        DB_SET          0x010000        /* c_get(), log_get() */
 #define        DB_SET_RANGE    0x020000        /* c_get() */
 #define        DB_SET_RECNO    0x040000        /* c_get() */
+#define        DB_CURLSN       0x080000        /* log_put() */
 
 /*
  * DB (user visible) error return codes.
@@ -435,14 +442,14 @@ struct __db {
        void *(*db_malloc) __P((size_t));
 
                                        /* Functions. */
-       int (*close)    __P((DB *, int));
+       int (*close)    __P((DB *, u_int32_t));
        int (*cursor)   __P((DB *, DB_TXN *, DBC **));
-       int (*del)      __P((DB *, DB_TXN *, DBT *, int));
+       int (*del)      __P((DB *, DB_TXN *, DBT *, u_int32_t));
        int (*fd)       __P((DB *, int *));
-       int (*get)      __P((DB *, DB_TXN *, DBT *, DBT *, int));
-       int (*put)      __P((DB *, DB_TXN *, DBT *, DBT *, int));
-       int (*stat)     __P((DB *, void *, void *(*)(size_t), int));
-       int (*sync)     __P((DB *, int));
+       int (*get)      __P((DB *, DB_TXN *, DBT *, DBT *, u_int32_t));
+       int (*put)      __P((DB *, DB_TXN *, DBT *, DBT *, u_int32_t));
+       int (*stat)     __P((DB *, void *, void *(*)(size_t), u_int32_t));
+       int (*sync)     __P((DB *, u_int32_t));
 
 #define        DB_AM_DUP       0x000001        /* DB_DUP (internal). */
 #define        DB_AM_INMEM     0x000002        /* In-memory; no sync on close. */
@@ -483,9 +490,9 @@ struct __dbc {
        void     *internal;             /* Access method private. */
 
        int (*c_close)  __P((DBC *));
-       int (*c_del)    __P((DBC *, int));
-       int (*c_get)    __P((DBC *, DBT *, DBT *, int));
-       int (*c_put)    __P((DBC *, DBT *, DBT *, int));
+       int (*c_del)    __P((DBC *, u_int32_t));
+       int (*c_get)    __P((DBC *, DBT *, DBT *, u_int32_t));
+       int (*c_put)    __P((DBC *, DBT *, DBT *, u_int32_t));
 };
 
 /* Btree/recno statistics structure. */
@@ -524,10 +531,11 @@ struct __db_bt_stat {
 #if defined(__cplusplus)
 extern "C" {
 #endif
-int   db_appinit __P((const char *, char * const *, DB_ENV *, int));
+int   db_appinit __P((const char *, char * const *, DB_ENV *, u_int32_t));
 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 **));
+int   db_open __P((const char *,
+         DBTYPE, u_int32_t, int, DB_ENV *, DB_INFO *, DB **));
 int   db_value_set __P((int, int));
 char *db_version __P((int *, int *, int *));
 #if defined(__cplusplus)
@@ -575,6 +583,21 @@ typedef enum {
        DB_LOCK_IWR                     /* Intent to read and write. */
 } db_lockmode_t;
 
+/*
+ * Status of a lock.
+ */
+typedef enum {
+       DB_LSTAT_ABORTED,               /* Lock belongs to an aborted txn. */
+       DB_LSTAT_ERR,                   /* Lock is bad. */
+       DB_LSTAT_FREE,                  /* Lock is unallocated. */
+       DB_LSTAT_HELD,                  /* Lock is currently held. */
+       DB_LSTAT_NOGRANT,               /* Lock was not granted. */
+       DB_LSTAT_PENDING,               /* Lock was waiting and has been
+                                        * promoted; waiting for the owner
+                                        * to run and upgrade it to held. */
+       DB_LSTAT_WAITING                /* Lock is on the wait queue. */
+} db_status_t;
+
 /* Lock request structure. */
 struct __db_lockreq {
        db_lockop_t      op;            /* Operation. */
@@ -596,19 +619,38 @@ extern const u_int8_t db_rw_conflicts[];
 #define        DB_LOCK_RIW_N   6
 extern const u_int8_t db_riw_conflicts[];
 
+struct __db_lock_stat {
+       u_int32_t st_magic;             /* Lock file magic number. */
+       u_int32_t st_version;           /* Lock file version number. */
+       u_int32_t st_maxlocks;          /* Maximum number of locks in table. */
+       u_int32_t st_nmodes;            /* Number of lock modes. */
+       u_int32_t st_numobjs;           /* Number of objects. */
+       u_int32_t st_nlockers;          /* Number of lockers. */
+       u_int32_t st_nconflicts;        /* Number of lock conflicts. */
+       u_int32_t st_nrequests;         /* Number of lock gets. */
+       u_int32_t st_nreleases;         /* Number of lock puts. */
+       u_int32_t st_ndeadlocks;        /* Number of lock deadlocks. */
+       u_int32_t st_region_wait;       /* Region lock granted after wait. */
+       u_int32_t st_region_nowait;     /* Region lock granted without wait. */
+       u_int32_t st_refcnt;            /* Region reference count. */
+       u_int32_t st_regsize;           /* Region size. */
+};
+
 #if defined(__cplusplus)
 extern "C" {
 #endif
 int      lock_close __P((DB_LOCKTAB *));
-int      lock_detect __P((DB_LOCKTAB *, int, int));
+int      lock_detect __P((DB_LOCKTAB *, u_int32_t, u_int32_t));
 int      lock_get __P((DB_LOCKTAB *,
-           u_int32_t, int, const DBT *, db_lockmode_t, DB_LOCK *));
+           u_int32_t, u_int32_t, const DBT *, db_lockmode_t, DB_LOCK *));
 int      lock_id __P((DB_LOCKTAB *, u_int32_t *));
-int      lock_open __P((const char *, int, int, DB_ENV *, DB_LOCKTAB **));
+int      lock_open __P((const char *,
+           u_int32_t, int, DB_ENV *, DB_LOCKTAB **));
 int      lock_put __P((DB_LOCKTAB *, DB_LOCK));
+int      lock_stat __P((DB_LOCKTAB *, DB_LOCK_STAT **, void *(*)(size_t)));
 int      lock_unlink __P((const char *, int, DB_ENV *));
 int      lock_vec __P((DB_LOCKTAB *,
-           u_int32_t, int, DB_LOCKREQ *, int, DB_LOCKREQ **));
+           u_int32_t, u_int32_t, DB_LOCKREQ *, int, DB_LOCKREQ **));
 #if defined(__cplusplus)
 }
 #endif
@@ -651,19 +693,21 @@ struct __db_log_stat {
        u_int32_t st_region_nowait;     /* Region lock granted without wait. */
        u_int32_t st_cur_file;          /* Current log file number. */
        u_int32_t st_cur_offset;        /* Current log file offset. */
+       u_int32_t st_refcnt;            /* Region reference count. */
+       u_int32_t st_regsize;           /* Region size. */
 };
 
 #if defined(__cplusplus)
 extern "C" {
 #endif
-int     log_archive __P((DB_LOG *, char **[], int, void *(*)(size_t)));
+int     log_archive __P((DB_LOG *, char **[], u_int32_t, void *(*)(size_t)));
 int     log_close __P((DB_LOG *));
 int     log_compare __P((const DB_LSN *, const DB_LSN *));
 int     log_file __P((DB_LOG *, const DB_LSN *, char *, size_t));
 int     log_flush __P((DB_LOG *, const DB_LSN *));
-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_get __P((DB_LOG *, DB_LSN *, DBT *, u_int32_t));
+int     log_open __P((const char *, u_int32_t, int, DB_ENV *, DB_LOG **));
+int     log_put __P((DB_LOG *, DB_LSN *, const DBT *, u_int32_t));
 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 *));
@@ -705,6 +749,17 @@ struct __db_mpool_stat {
        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. */
+       u_int32_t st_refcnt;            /* Region reference count. */
+       u_int32_t st_regsize;           /* Region size. */
+};
+
+/* Mpool file open information structure. */
+struct __db_mpool_finfo {
+       int        ftype;               /* File type. */
+       DBT       *pgcookie;            /* Byte-string passed to pgin/pgout. */
+       u_int8_t  *fileid;              /* Unique file ID. */
+       int32_t    lsn_offset;          /* LSN offset in page. */
+       u_int32_t  clear_len;           /* Cleared length on created pages. */
 };
 
 /* Mpool file statistics structure. */
@@ -724,13 +779,13 @@ extern "C" {
 #endif
 int    memp_close __P((DB_MPOOL *));
 int    memp_fclose __P((DB_MPOOLFILE *));
-int    memp_fget __P((DB_MPOOLFILE *, db_pgno_t *, int, void *));
+int    memp_fget __P((DB_MPOOLFILE *, db_pgno_t *, u_int32_t, void *));
 int    memp_fopen __P((DB_MPOOL *, const char *,
-           int, int, int, size_t, int, DBT *, u_int8_t *, DB_MPOOLFILE **));
-int    memp_fput __P((DB_MPOOLFILE *, void *, int));
-int    memp_fset __P((DB_MPOOLFILE *, void *, int));
+           u_int32_t, int, size_t, DB_MPOOL_FINFO *, DB_MPOOLFILE **));
+int    memp_fput __P((DB_MPOOLFILE *, void *, u_int32_t));
+int    memp_fset __P((DB_MPOOLFILE *, void *, u_int32_t));
 int    memp_fsync __P((DB_MPOOLFILE *));
-int    memp_open __P((const char *, int, int, DB_ENV *, DB_MPOOL **));
+int    memp_open __P((const char *, u_int32_t, int, DB_ENV *, DB_MPOOL **));
 int    memp_register __P((DB_MPOOL *, int,
            int (*)(db_pgno_t, void *, DBT *),
            int (*)(db_pgno_t, void *, DBT *)));
@@ -765,16 +820,21 @@ struct __db_txn_active {
 };
 
 struct __db_txn_stat {
-       DB_LSN          st_last_ckp;    /* lsn of the last checkpoint */
-       DB_LSN          st_pending_ckp; /* last checkpoint did not finish */
-       time_t          st_time_ckp;    /* time of last checkpoint */
-       u_int32_t       st_last_txnid;  /* last transaction id given out */
-       u_int32_t       st_maxtxns;     /* maximum number of active txns */
-       u_int32_t       st_naborts;     /* number of aborted transactions */
-       u_int32_t       st_nbegins;     /* number of begun transactions */
-       u_int32_t       st_ncommits;    /* number of committed transactions */
-       u_int32_t       st_nactive;     /* number of active transactions */
-       DB_TXN_ACTIVE   *st_txnarray;   /* array of active transactions */
+       DB_LSN    st_last_ckp;          /* lsn of the last checkpoint */
+       DB_LSN    st_pending_ckp;       /* last checkpoint did not finish */
+       time_t    st_time_ckp;          /* time of last checkpoint */
+       u_int32_t st_last_txnid;        /* last transaction id given out */
+       u_int32_t st_maxtxns;   /* maximum number of active txns */
+       u_int32_t st_naborts;   /* number of aborted transactions */
+       u_int32_t st_nbegins;   /* number of begun transactions */
+       u_int32_t st_ncommits;  /* number of committed transactions */
+       u_int32_t st_nactive;   /* number of active transactions */
+       DB_TXN_ACTIVE
+                *st_txnarray;  /* array of active transactions */
+       u_int32_t st_region_wait;       /* Region lock granted after wait. */
+       u_int32_t st_region_nowait;     /* Region lock granted without wait. */
+       u_int32_t st_refcnt;            /* Region reference count. */
+       u_int32_t st_regsize;           /* Region size. */
 };
 
 #if defined(__cplusplus)
@@ -782,11 +842,11 @@ extern "C" {
 #endif
 int      txn_abort __P((DB_TXN *));
 int      txn_begin __P((DB_TXNMGR *, DB_TXN *, DB_TXN **));
-int      txn_checkpoint __P((const DB_TXNMGR *, int, int));
+int      txn_checkpoint __P((const DB_TXNMGR *, u_int32_t, u_int32_t));
 int      txn_commit __P((DB_TXN *));
 int      txn_close __P((DB_TXNMGR *));
 u_int32_t txn_id __P((DB_TXN *));
-int      txn_open __P((const char *, int, int, DB_ENV *, DB_TXNMGR **));
+int      txn_open __P((const char *, u_int32_t, int, DB_ENV *, DB_TXNMGR **));
 int      txn_prepare __P((DB_TXN *));
 int      txn_stat __P((DB_TXNMGR *, DB_TXN_STAT **, void *(*)(size_t)));
 int      txn_unlink __P((const char *, int, DB_ENV *));
@@ -810,10 +870,17 @@ int         txn_unlink __P((const char *, int, DB_ENV *));
  */
 #define        DBM_SUFFIX      ".db"
 
+#if defined(_XPG4_2)
+typedef struct {
+       char *dptr;
+       size_t dsize;
+} datum;
+#else
 typedef struct {
        char *dptr;
        int dsize;
 } datum;
+#endif
 
 /*
  * Translate DBM calls into DB calls so that DB doesn't step on the
@@ -894,7 +961,7 @@ typedef enum {
 
 typedef struct entry {
        char *key;
-       void *data;
+       char *data;
 } ENTRY;
 
 /*
@@ -909,7 +976,7 @@ typedef struct entry {
 #if defined(__cplusplus)
 extern "C" {
 #endif
-int     __db_hcreate __P((unsigned int));
+int     __db_hcreate __P((size_t));
 void    __db_hdestroy __P((void));
 ENTRY  *__db_hsearch __P((ENTRY, ACTION));
 #if defined(__cplusplus)
index 8df7634..9951ebd 100644 (file)
@@ -1,7 +1,7 @@
 /*-
  * See the file LICENSE for redistribution information.
  *
- * Copyright (c) 1996, 1997
+ * Copyright (c) 1996, 1997, 1998
  *     Sleepycat Software.  All rights reserved.
  */
 /*
 #include "config.h"
 
 #ifndef lint
-static const char sccsid[] = "@(#)db.c 10.45 (Sleepycat) 12/4/97";
+static const char sccsid[] = "@(#)db.c 10.57 (Sleepycat) 5/7/98";
 #endif /* not lint */
 
 #ifndef NO_SYSTEM_INCLUDES
 #include <sys/types.h>
-#include <sys/stat.h>
 
 #include <errno.h>
-#include <fcntl.h>
 #include <stddef.h>
-#include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
-#include <unistd.h>
 #endif
 
 #include "db_int.h"
@@ -71,7 +67,7 @@ static const char sccsid[] = "@(#)db.c        10.45 (Sleepycat) 12/4/97";
 #include "db_am.h"
 #include "common_ext.h"
 
-static int db_close __P((DB *, int));
+static int db_close __P((DB *, u_int32_t));
 static int db_fd __P((DB *, int *));
 
 /*
@@ -99,7 +95,8 @@ int
 db_open(fname, type, flags, mode, dbenv, dbinfo, dbpp)
        const char *fname;
        DBTYPE type;
-       int flags, mode;
+       u_int32_t flags;
+       int mode;
        DB_ENV *dbenv;
        DB_INFO *dbinfo;
        DB **dbpp;
@@ -108,6 +105,7 @@ db_open(fname, type, flags, mode, dbenv, dbinfo, dbpp)
        DB *dbp;
        DBT pgcookie;
        DB_ENV *envp, t_dbenv;
+       DB_MPOOL_FINFO finfo;
        DB_PGINFO pginfo;
        HASHHDR *hashm;
        size_t cachesize;
@@ -125,10 +123,26 @@ 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);
+       if (dbenv != NULL) {
+               /*
+                * You can't specify threads during the db_open() if the
+                * environment wasn't configured with them.
+                */
+               if (LF_ISSET(DB_THREAD) && !F_ISSET(dbenv, DB_ENV_THREAD)) {
+                       __db_err(dbenv,
+                           "environment not created using DB_THREAD");
+                       return (EINVAL);
+               }
+
+               /*
+                * Specifying a cachesize to db_open(3), after creating an
+                * environment, is a common mistake.
+                */
+               if (dbinfo != NULL && dbinfo->db_cachesize != 0) {
+                       __db_err(dbenv,
+                           "cachesize will be ignored if environment exists");
+                       return (EINVAL);
+               }
        }
 
        /* Initialize for error return. */
@@ -203,7 +217,7 @@ db_open(fname, type, flags, mode, dbenv, dbinfo, dbpp)
 
        /* Fill in the default file mode. */
        if (mode == 0)
-               mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP;
+               mode = __db_omode("rwrw--");
 
        /* Check if the user wants us to swap byte order. */
        if (dbinfo != NULL)
@@ -230,7 +244,7 @@ db_open(fname, type, flags, mode, dbenv, dbinfo, dbpp)
        if (fname != NULL && fname[0] != '\0') {
                /* Get the real file name. */
                if ((ret = __db_appname(dbenv,
-                    DB_APP_DATA, NULL, fname, NULL, &real_name)) != 0)
+                    DB_APP_DATA, NULL, fname, 0, NULL, &real_name)) != 0)
                        goto err;
 
                /*
@@ -455,22 +469,6 @@ empty:     /*
        }
 
        /*
-        * Set and/or correct the cache size; must be a multiple of the
-        * page size.
-        */
-       if (dbinfo == NULL || dbinfo->db_cachesize == 0)
-               cachesize = dbp->pgsize * DB_MINCACHE;
-       else {
-               cachesize = dbinfo->db_cachesize;
-               if (cachesize & (dbp->pgsize - 1))
-                       cachesize += (~cachesize & (dbp->pgsize - 1)) + 1;
-               if (cachesize < dbp->pgsize * DB_MINCACHE)
-                       cachesize = dbp->pgsize * DB_MINCACHE;
-               if (cachesize < 20 * 1024)
-                       cachesize = 20 * 1024;
-       }
-
-       /*
         * If no mpool supplied by the application, attach to a local,
         * created buffer pool.
         *
@@ -499,10 +497,28 @@ empty:    /*
                        envp = dbenv;
                        restore = 1;
                }
+
+               /*
+                * Set and/or correct the cache size; must be a multiple of
+                * the page size.
+                */
+               if (dbinfo == NULL || dbinfo->db_cachesize == 0)
+                       cachesize = dbp->pgsize * DB_MINCACHE;
+               else {
+                       cachesize = dbinfo->db_cachesize;
+                       if (cachesize & (dbp->pgsize - 1))
+                               cachesize +=
+                                   (~cachesize & (dbp->pgsize - 1)) + 1;
+                       if (cachesize < dbp->pgsize * DB_MINCACHE)
+                               cachesize = dbp->pgsize * DB_MINCACHE;
+                       if (cachesize < 20 * 1024)
+                               cachesize = 20 * 1024;
+               }
                envp->mp_size = cachesize;
+
                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)
+                   __db_omode("rw----"), envp, &dbp->mp)) != 0)
                        goto err;
                if (restore)
                        *dbenv = t_dbenv;
@@ -566,9 +582,18 @@ empty:     /*
        pgcookie.data = &pginfo;
        pgcookie.size = sizeof(DB_PGINFO);
 
-       if ((ret = memp_fopen(dbp->mp, fname, ftype,
-           F_ISSET(dbp, DB_AM_RDONLY) ? DB_RDONLY : 0, 0, dbp->pgsize,
-           0, &pgcookie, dbp->lock.fileid, &dbp->mpf)) != 0)
+       /*
+        * Set up additional memp_fopen information.
+        */
+       memset(&finfo, 0, sizeof(finfo));
+       finfo.ftype = ftype;
+       finfo.pgcookie = &pgcookie;
+       finfo.fileid = dbp->lock.fileid;
+       finfo.lsn_offset = 0;
+       finfo.clear_len = DB_PAGE_CLEAR_LEN;
+       if ((ret = memp_fopen(dbp->mp, fname,
+           F_ISSET(dbp, DB_AM_RDONLY) ? DB_RDONLY : 0,
+           0, dbp->pgsize, &finfo, &dbp->mpf)) != 0)
                goto err;
 
        /*
@@ -673,7 +698,7 @@ err:        /* Close the file descriptor. */
 static int
 db_close(dbp, flags)
        DB *dbp;
-       int flags;
+       u_int32_t flags;
 {
        DBC *dbc;
        DB *tdbp;
@@ -734,7 +759,7 @@ db_close(dbp, flags)
        }
 
        /* Sync the memory pool. */
-       if ((t_ret = memp_fsync(dbp->mpf)) != 0 &&
+       if (!LF_ISSET(DB_NOSYNC) && (t_ret = memp_fsync(dbp->mpf)) != 0 &&
            t_ret != DB_INCOMPLETE && ret == 0)
                ret = t_ret;
 
@@ -796,18 +821,11 @@ db_fd(dbp, fdp)
         DB *dbp;
        int *fdp;
 {
-       /* In-memory database can't have a file descriptor. */
-       if (F_ISSET(dbp, DB_AM_INMEM))
-               return (ENOENT);
-
        /*
         * XXX
-        * Truly spectacular layering violation.  As we don't open the
-        * underlying file until we need it, it may not be initialized.
+        * Truly spectacular layering violation.
         */
-       if ((*fdp = dbp->mpf->fd) == -1)
-               return (ENOENT);
-       return (0);
+       return (__mp_xxx_fd(dbp->mpf, fdp));
 }
 
 /*
@@ -821,6 +839,11 @@ __db_pgerr(dbp, pgno)
        DB *dbp;
        db_pgno_t pgno;
 {
+       /*
+        * Three things are certain:
+        * Death, taxes, and lost data.
+        * Guess which has occurred.
+        */
        __db_err(dbp->dbenv,
            "unable to create/retrieve page %lu", (u_long)pgno);
        return (__db_panic(dbp));
index 07d9812..91d8b39 100644 (file)
@@ -1,11 +1,11 @@
 /*-
  * See the file LICENSE for redistribution information.
  *
- * Copyright (c) 1996, 1997
+ * Copyright (c) 1996, 1997, 1998
  *     Sleepycat Software.  All rights reserved.
- *     @(#)db.src      10.4 (Sleepycat) 11/2/97
+ *
+ *     @(#)db.src      10.6 (Sleepycat) 4/28/98
  */
-#include "config.h"
 
 PREFIX db
 
@@ -153,4 +153,7 @@ END
  * noop -- do nothing, but get an LSN.
  */
 BEGIN noop
+ARG    fileid          u_int32_t       lu
+ARG    pgno            db_pgno_t       lu
+POINTER        prevlsn         DB_LSN *        lu
 END
index 5d35264..5203e0a 100644 (file)
@@ -14,8 +14,6 @@
 #include "db_page.h"
 #include "db_dispatch.h"
 #include "db_am.h"
-#include "common_ext.h"
-
 /*
  * PUBLIC: int __db_addrem_log
  * PUBLIC:     __P((DB_LOG *, DB_TXN *, DB_LSN *, u_int32_t,
@@ -107,7 +105,7 @@ int __db_addrem_log(logp, txnid, ret_lsnp, flags,
        else
                memset(bp, 0, sizeof(*pagelsn));
        bp += sizeof(*pagelsn);
-#ifdef DEBUG
+#ifdef DIAGNOSTIC
        if ((u_int32_t)(bp - (u_int8_t *)logrec.data) != logrec.size)
                fprintf(stderr, "Error in log record length");
 #endif
@@ -123,22 +121,23 @@ int __db_addrem_log(logp, txnid, ret_lsnp, flags,
  * PUBLIC:    __P((DB_LOG *, DBT *, DB_LSN *, int, void *));
  */
 int
-__db_addrem_print(notused1, dbtp, lsnp, notused3, notused4)
+__db_addrem_print(notused1, dbtp, lsnp, notused2, notused3)
        DB_LOG *notused1;
        DBT *dbtp;
        DB_LSN *lsnp;
-       int notused3;
-       void *notused4;
+       int notused2;
+       void *notused3;
 {
        __db_addrem_args *argp;
        u_int32_t i;
-       int c, ret;
+       u_int ch;
+       int ret;
 
        i = 0;
-       c = 0;
+       ch = 0;
        notused1 = NULL;
-       notused3 = 0;
-       notused4 = NULL;
+       notused2 = 0;
+       notused3 = NULL;
 
        if ((ret = __db_addrem_read(dbtp->data, &argp)) != 0)
                return (ret);
@@ -156,20 +155,20 @@ __db_addrem_print(notused1, dbtp, lsnp, notused3, notused4)
        printf("\tnbytes: %lu\n", (u_long)argp->nbytes);
        printf("\thdr: ");
        for (i = 0; i < argp->hdr.size; i++) {
-               c = ((char *)argp->hdr.data)[i];
-               if (isprint(c) || c == 0xa)
-                       putchar(c);
+               ch = ((u_int8_t *)argp->hdr.data)[i];
+               if (isprint(ch) || ch == 0xa)
+                       putchar(ch);
                else
-                       printf("%#x ", c);
+                       printf("%#x ", ch);
        }
        printf("\n");
        printf("\tdbt: ");
        for (i = 0; i < argp->dbt.size; i++) {
-               c = ((char *)argp->dbt.data)[i];
-               if (isprint(c) || c == 0xa)
-                       putchar(c);
+               ch = ((u_int8_t *)argp->dbt.data)[i];
+               if (isprint(ch) || ch == 0xa)
+                       putchar(ch);
                else
-                       printf("%#x ", c);
+                       printf("%#x ", ch);
        }
        printf("\n");
        printf("\tpagelsn: [%lu][%lu]\n",
@@ -296,7 +295,7 @@ int __db_split_log(logp, txnid, ret_lsnp, flags,
        else
                memset(bp, 0, sizeof(*pagelsn));
        bp += sizeof(*pagelsn);
-#ifdef DEBUG
+#ifdef DIAGNOSTIC
        if ((u_int32_t)(bp - (u_int8_t *)logrec.data) != logrec.size)
                fprintf(stderr, "Error in log record length");
 #endif
@@ -312,22 +311,23 @@ int __db_split_log(logp, txnid, ret_lsnp, flags,
  * PUBLIC:    __P((DB_LOG *, DBT *, DB_LSN *, int, void *));
  */
 int
-__db_split_print(notused1, dbtp, lsnp, notused3, notused4)
+__db_split_print(notused1, dbtp, lsnp, notused2, notused3)
        DB_LOG *notused1;
        DBT *dbtp;
        DB_LSN *lsnp;
-       int notused3;
-       void *notused4;
+       int notused2;
+       void *notused3;
 {
        __db_split_args *argp;
        u_int32_t i;
-       int c, ret;
+       u_int ch;
+       int ret;
 
        i = 0;
-       c = 0;
+       ch = 0;
        notused1 = NULL;
-       notused3 = 0;
-       notused4 = NULL;
+       notused2 = 0;
+       notused3 = NULL;
 
        if ((ret = __db_split_read(dbtp->data, &argp)) != 0)
                return (ret);
@@ -343,11 +343,11 @@ __db_split_print(notused1, dbtp, lsnp, notused3, notused4)
        printf("\tpgno: %lu\n", (u_long)argp->pgno);
        printf("\tpageimage: ");
        for (i = 0; i < argp->pageimage.size; i++) {
-               c = ((char *)argp->pageimage.data)[i];
-               if (isprint(c) || c == 0xa)
-                       putchar(c);
+               ch = ((u_int8_t *)argp->pageimage.data)[i];
+               if (isprint(ch) || ch == 0xa)
+                       putchar(ch);
                else
-                       printf("%#x ", c);
+                       printf("%#x ", ch);
        }
        printf("\n");
        printf("\tpagelsn: [%lu][%lu]\n",
@@ -490,7 +490,7 @@ int __db_big_log(logp, txnid, ret_lsnp, flags,
        else
                memset(bp, 0, sizeof(*nextlsn));
        bp += sizeof(*nextlsn);
-#ifdef DEBUG
+#ifdef DIAGNOSTIC
        if ((u_int32_t)(bp - (u_int8_t *)logrec.data) != logrec.size)
                fprintf(stderr, "Error in log record length");
 #endif
@@ -506,22 +506,23 @@ int __db_big_log(logp, txnid, ret_lsnp, flags,
  * PUBLIC:    __P((DB_LOG *, DBT *, DB_LSN *, int, void *));
  */
 int
-__db_big_print(notused1, dbtp, lsnp, notused3, notused4)
+__db_big_print(notused1, dbtp, lsnp, notused2, notused3)
        DB_LOG *notused1;
        DBT *dbtp;
        DB_LSN *lsnp;
-       int notused3;
-       void *notused4;
+       int notused2;
+       void *notused3;
 {
        __db_big_args *argp;
        u_int32_t i;
-       int c, ret;
+       u_int ch;
+       int ret;
 
        i = 0;
-       c = 0;
+       ch = 0;
        notused1 = NULL;
-       notused3 = 0;
-       notused4 = NULL;
+       notused2 = 0;
+       notused3 = NULL;
 
        if ((ret = __db_big_read(dbtp->data, &argp)) != 0)
                return (ret);
@@ -539,11 +540,11 @@ __db_big_print(notused1, dbtp, lsnp, notused3, notused4)
        printf("\tnext_pgno: %lu\n", (u_long)argp->next_pgno);
        printf("\tdbt: ");
        for (i = 0; i < argp->dbt.size; i++) {
-               c = ((char *)argp->dbt.data)[i];
-               if (isprint(c) || c == 0xa)
-                       putchar(c);
+               ch = ((u_int8_t *)argp->dbt.data)[i];
+               if (isprint(ch) || ch == 0xa)
+                       putchar(ch);
                else
-                       printf("%#x ", c);
+                       printf("%#x ", ch);
        }
        printf("\n");
        printf("\tpagelsn: [%lu][%lu]\n",
@@ -660,7 +661,7 @@ int __db_ovref_log(logp, txnid, ret_lsnp, flags,
        else
                memset(bp, 0, sizeof(*lsn));
        bp += sizeof(*lsn);
-#ifdef DEBUG
+#ifdef DIAGNOSTIC
        if ((u_int32_t)(bp - (u_int8_t *)logrec.data) != logrec.size)
                fprintf(stderr, "Error in log record length");
 #endif
@@ -676,22 +677,23 @@ int __db_ovref_log(logp, txnid, ret_lsnp, flags,
  * PUBLIC:    __P((DB_LOG *, DBT *, DB_LSN *, int, void *));
  */
 int
-__db_ovref_print(notused1, dbtp, lsnp, notused3, notused4)
+__db_ovref_print(notused1, dbtp, lsnp, notused2, notused3)
        DB_LOG *notused1;
        DBT *dbtp;
        DB_LSN *lsnp;
-       int notused3;
-       void *notused4;
+       int notused2;
+       void *notused3;
 {
        __db_ovref_args *argp;
        u_int32_t i;
-       int c, ret;
+       u_int ch;
+       int ret;
 
        i = 0;
-       c = 0;
+       ch = 0;
        notused1 = NULL;
-       notused3 = 0;
-       notused4 = NULL;
+       notused2 = 0;
+       notused3 = NULL;
 
        if ((ret = __db_ovref_read(dbtp->data, &argp)) != 0)
                return (ret);
@@ -823,7 +825,7 @@ int __db_relink_log(logp, txnid, ret_lsnp, flags,
        else
                memset(bp, 0, sizeof(*lsn_next));
        bp += sizeof(*lsn_next);
-#ifdef DEBUG
+#ifdef DIAGNOSTIC
        if ((u_int32_t)(bp - (u_int8_t *)logrec.data) != logrec.size)
                fprintf(stderr, "Error in log record length");
 #endif
@@ -839,22 +841,23 @@ int __db_relink_log(logp, txnid, ret_lsnp, flags,
  * PUBLIC:    __P((DB_LOG *, DBT *, DB_LSN *, int, void *));
  */
 int
-__db_relink_print(notused1, dbtp, lsnp, notused3, notused4)
+__db_relink_print(notused1, dbtp, lsnp, notused2, notused3)
        DB_LOG *notused1;
        DBT *dbtp;
        DB_LSN *lsnp;
-       int notused3;
-       void *notused4;
+       int notused2;
+       void *notused3;
 {
        __db_relink_args *argp;
        u_int32_t i;
-       int c, ret;
+       u_int ch;
+       int ret;
 
        i = 0;
-       c = 0;
+       ch = 0;
        notused1 = NULL;
-       notused3 = 0;
-       notused4 = NULL;
+       notused2 = 0;
+       notused3 = NULL;
 
        if ((ret = __db_relink_read(dbtp->data, &argp)) != 0)
                return (ret);
@@ -985,7 +988,7 @@ int __db_addpage_log(logp, txnid, ret_lsnp, flags,
        else
                memset(bp, 0, sizeof(*nextlsn));
        bp += sizeof(*nextlsn);
-#ifdef DEBUG
+#ifdef DIAGNOSTIC
        if ((u_int32_t)(bp - (u_int8_t *)logrec.data) != logrec.size)
                fprintf(stderr, "Error in log record length");
 #endif
@@ -1001,22 +1004,23 @@ int __db_addpage_log(logp, txnid, ret_lsnp, flags,
  * PUBLIC:    __P((DB_LOG *, DBT *, DB_LSN *, int, void *));
  */
 int
-__db_addpage_print(notused1, dbtp, lsnp, notused3, notused4)
+__db_addpage_print(notused1, dbtp, lsnp, notused2, notused3)
        DB_LOG *notused1;
        DBT *dbtp;
        DB_LSN *lsnp;
-       int notused3;
-       void *notused4;
+       int notused2;
+       void *notused3;
 {
        __db_addpage_args *argp;
        u_int32_t i;
-       int c, ret;
+       u_int ch;
+       int ret;
 
        i = 0;
-       c = 0;
+       ch = 0;
        notused1 = NULL;
-       notused3 = 0;
-       notused4 = NULL;
+       notused2 = 0;
+       notused3 = NULL;
 
        if ((ret = __db_addpage_read(dbtp->data, &argp)) != 0)
                return (ret);
@@ -1159,7 +1163,7 @@ int __db_debug_log(logp, txnid, ret_lsnp, flags,
        }
        memcpy(bp, &arg_flags, sizeof(arg_flags));
        bp += sizeof(arg_flags);
-#ifdef DEBUG
+#ifdef DIAGNOSTIC
        if ((u_int32_t)(bp - (u_int8_t *)logrec.data) != logrec.size)
                fprintf(stderr, "Error in log record length");
 #endif
@@ -1175,22 +1179,23 @@ int __db_debug_log(logp, txnid, ret_lsnp, flags,
  * PUBLIC:    __P((DB_LOG *, DBT *, DB_LSN *, int, void *));
  */
 int
-__db_debug_print(notused1, dbtp, lsnp, notused3, notused4)
+__db_debug_print(notused1, dbtp, lsnp, notused2, notused3)
        DB_LOG *notused1;
        DBT *dbtp;
        DB_LSN *lsnp;
-       int notused3;
-       void *notused4;
+       int notused2;
+       void *notused3;
 {
        __db_debug_args *argp;
        u_int32_t i;
-       int c, ret;
+       u_int ch;
+       int ret;
 
        i = 0;
-       c = 0;
+       ch = 0;
        notused1 = NULL;
-       notused3 = 0;
-       notused4 = NULL;
+       notused2 = 0;
+       notused3 = NULL;
 
        if ((ret = __db_debug_read(dbtp->data, &argp)) != 0)
                return (ret);
@@ -1203,30 +1208,30 @@ __db_debug_print(notused1, dbtp, lsnp, notused3, notused4)
            (u_long)argp->prev_lsn.offset);
        printf("\top: ");
        for (i = 0; i < argp->op.size; i++) {
-               c = ((char *)argp->op.data)[i];
-               if (isprint(c) || c == 0xa)
-                       putchar(c);
+               ch = ((u_int8_t *)argp->op.data)[i];
+               if (isprint(ch) || ch == 0xa)
+                       putchar(ch);
                else
-                       printf("%#x ", c);
+                       printf("%#x ", ch);
        }
        printf("\n");
        printf("\tfileid: %lu\n", (u_long)argp->fileid);
        printf("\tkey: ");
        for (i = 0; i < argp->key.size; i++) {
-               c = ((char *)argp->key.data)[i];
-               if (isprint(c) || c == 0xa)
-                       putchar(c);
+               ch = ((u_int8_t *)argp->key.data)[i];
+               if (isprint(ch) || ch == 0xa)
+                       putchar(ch);
                else
-                       printf("%#x ", c);
+                       printf("%#x ", ch);
        }
        printf("\n");
        printf("\tdata: ");
        for (i = 0; i < argp->data.size; i++) {
-               c = ((char *)argp->data.data)[i];
-               if (isprint(c) || c == 0xa)
-                       putchar(c);
+               ch = ((u_int8_t *)argp->data.data)[i];
+               if (isprint(ch) || ch == 0xa)
+                       putchar(ch);
                else
-                       printf("%#x ", c);
+                       printf("%#x ", ch);
        }
        printf("\n");
        printf("\targ_flags: %lu\n", (u_long)argp->arg_flags);
@@ -1280,13 +1285,18 @@ __db_debug_read(recbuf, argpp)
 
 /*
  * PUBLIC: int __db_noop_log
- * PUBLIC:     __P((DB_LOG *, DB_TXN *, DB_LSN *, u_int32_t));
+ * PUBLIC:     __P((DB_LOG *, DB_TXN *, DB_LSN *, u_int32_t,
+ * PUBLIC:     u_int32_t, db_pgno_t, DB_LSN *));
  */
-int __db_noop_log(logp, txnid, ret_lsnp, flags)
+int __db_noop_log(logp, txnid, ret_lsnp, flags,
+       fileid, pgno, prevlsn)
        DB_LOG *logp;
        DB_TXN *txnid;
        DB_LSN *ret_lsnp;
        u_int32_t flags;
+       u_int32_t fileid;
+       db_pgno_t pgno;
+       DB_LSN * prevlsn;
 {
        DBT logrec;
        DB_LSN *lsnp, null_lsn;
@@ -1302,7 +1312,10 @@ int __db_noop_log(logp, txnid, ret_lsnp, flags)
                lsnp = &null_lsn;
        } else
                lsnp = &txnid->last_lsn;
-       logrec.size = sizeof(rectype) + sizeof(txn_num) + sizeof(DB_LSN);
+       logrec.size = sizeof(rectype) + sizeof(txn_num) + sizeof(DB_LSN)
+           + sizeof(fileid)
+           + sizeof(pgno)
+           + sizeof(*prevlsn);
        if ((logrec.data = (void *)__db_malloc(logrec.size)) == NULL)
                return (ENOMEM);
 
@@ -1313,7 +1326,16 @@ int __db_noop_log(logp, txnid, ret_lsnp, flags)
        bp += sizeof(txn_num);
        memcpy(bp, lsnp, sizeof(DB_LSN));
        bp += sizeof(DB_LSN);
-#ifdef DEBUG
+       memcpy(bp, &fileid, sizeof(fileid));
+       bp += sizeof(fileid);
+       memcpy(bp, &pgno, sizeof(pgno));
+       bp += sizeof(pgno);
+       if (prevlsn != NULL)
+               memcpy(bp, prevlsn, sizeof(*prevlsn));
+       else
+               memset(bp, 0, sizeof(*prevlsn));
+       bp += sizeof(*prevlsn);
+#ifdef DIAGNOSTIC
        if ((u_int32_t)(bp - (u_int8_t *)logrec.data) != logrec.size)
                fprintf(stderr, "Error in log record length");
 #endif
@@ -1329,22 +1351,23 @@ int __db_noop_log(logp, txnid, ret_lsnp, flags)
  * PUBLIC:    __P((DB_LOG *, DBT *, DB_LSN *, int, void *));
  */
 int
-__db_noop_print(notused1, dbtp, lsnp, notused3, notused4)
+__db_noop_print(notused1, dbtp, lsnp, notused2, notused3)
        DB_LOG *notused1;
        DBT *dbtp;
        DB_LSN *lsnp;
-       int notused3;
-       void *notused4;
+       int notused2;
+       void *notused3;
 {
        __db_noop_args *argp;
        u_int32_t i;
-       int c, ret;
+       u_int ch;
+       int ret;
 
        i = 0;
-       c = 0;
+       ch = 0;
        notused1 = NULL;
-       notused3 = 0;
-       notused4 = NULL;
+       notused2 = 0;
+       notused3 = NULL;
 
        if ((ret = __db_noop_read(dbtp->data, &argp)) != 0)
                return (ret);
@@ -1355,6 +1378,10 @@ __db_noop_print(notused1, dbtp, lsnp, notused3, notused4)
            (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("\tprevlsn: [%lu][%lu]\n",
+           (u_long)argp->prevlsn.file, (u_long)argp->prevlsn.offset);
        printf("\n");
        __db_free(argp);
        return (0);
@@ -1383,6 +1410,12 @@ __db_noop_read(recbuf, argpp)
        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->prevlsn, bp,  sizeof(argp->prevlsn));
+       bp += sizeof(argp->prevlsn);
        *argpp = argp;
        return (0);
 }
index e9c4bf9..8b5cf5f 100644 (file)
@@ -1,7 +1,7 @@
 /*-
  * See the file LICENSE for redistribution information.
  *
- * Copyright (c) 1996, 1997
+ * Copyright (c) 1996, 1997, 1998
  *     Sleepycat Software.  All rights reserved.
  */
 /*
@@ -44,7 +44,7 @@
 #include "config.h"
 
 #ifndef lint
-static const char sccsid[] = "@(#)db_conv.c    10.8 (Sleepycat) 1/8/98";
+static const char sccsid[] = "@(#)db_conv.c    10.13 (Sleepycat) 4/26/98";
 #endif /* not lint */
 
 #ifndef NO_SYSTEM_INCLUDES
@@ -160,6 +160,13 @@ __db_convert(pg, pp, pagesize, pgin)
                        }
 
                }
+
+               /*
+                * The offsets in the inp array are used to determine
+                * the size of entries on a page; therefore they
+                * cannot be converted until we've done all the
+                * entries.
+                */
                if (!pgin)
                        for (i = 0; i < NUM_ENT(h); i++)
                                M_16_SWAP(h->inp[i]);
@@ -179,8 +186,8 @@ __db_convert(pg, pp, pagesize, pgin)
                        case B_DUPLICATE:
                        case B_OVERFLOW:
                                bo = (BOVERFLOW *)bk;
-                               M_32_SWAP(bo->tlen);
                                M_32_SWAP(bo->pgno);
+                               M_32_SWAP(bo->tlen);
                                break;
                        }
 
@@ -194,17 +201,18 @@ __db_convert(pg, pp, pagesize, pgin)
                                M_16_SWAP(h->inp[i]);
 
                        bi = GET_BINTERNAL(h, i);
+                       M_16_SWAP(bi->len);
+                       M_32_SWAP(bi->pgno);
+                       M_32_SWAP(bi->nrecs);
+
                        switch (B_TYPE(bi->type)) {
                        case B_KEYDATA:
-                               M_16_SWAP(bi->len);
-                               M_32_SWAP(bi->pgno);
-                               M_32_SWAP(bi->nrecs);
                                break;
                        case B_DUPLICATE:
                        case B_OVERFLOW:
-                               bo = (BOVERFLOW *)bi;
-                               M_32_SWAP(bo->tlen);
+                               bo = (BOVERFLOW *)bi->data;
                                M_32_SWAP(bo->pgno);
+                               M_32_SWAP(bo->tlen);
                                break;
                        }
 
@@ -224,6 +232,7 @@ __db_convert(pg, pp, pagesize, pgin)
                        if (!pgin)
                                M_16_SWAP(h->inp[i]);
                }
+               break;
        case P_OVERFLOW:
        case P_INVALID:
                /* Nothing to do. */
index 736575a..8645948 100644 (file)
@@ -1,7 +1,7 @@
 /*-
  * See the file LICENSE for redistribution information.
  *
- * Copyright (c) 1996, 1997
+ * Copyright (c) 1996, 1997, 1998
  *     Sleepycat Software.  All rights reserved.
  */
 /*
 #include "config.h"
 
 #ifndef lint
-static const char sccsid[] = "@(#)db_dispatch.c        10.9 (Sleepycat) 1/17/98";
+static const char sccsid[] = "@(#)db_dispatch.c        10.14 (Sleepycat) 5/3/98";
 #endif /* not lint */
 
 #ifndef NO_SYSTEM_INCLUDES
 #include <sys/types.h>
 
 #include <errno.h>
-#include <fcntl.h>
 #include <stddef.h>
 #include <stdlib.h>
 #include <string.h>
@@ -62,6 +61,7 @@ static const char sccsid[] = "@(#)db_dispatch.c       10.9 (Sleepycat) 1/17/98";
 #include "db_am.h"
 #include "common_ext.h"
 #include "log_auto.h"
+#include "txn_auto.h"
 
 /*
  * Data structures to manage the DB dispatch table.  The dispatch table
@@ -114,7 +114,7 @@ __db_dispatch(logp, db, lsnp, redo, info)
                 * seen it, then we call the appropriate recovery routine
                 * in "abort mode".
                 */
-               if (rectype == DB_log_register ||
+               if (rectype == DB_log_register || rectype == DB_txn_ckp ||
                    __db_txnlist_find(info, txnid) == DB_NOTFOUND)
                        return ((dispatch_table[rectype])(logp,
                            db, lsnp, TXN_UNDO, info));
@@ -124,7 +124,7 @@ __db_dispatch(logp, db, lsnp, redo, info)
                 * In the forward pass, if we haven't seen the transaction,
                 * do nothing, else recovery it.
                 */
-               if (rectype == DB_log_register ||
+               if (rectype == DB_log_register || rectype == DB_txn_ckp ||
                    __db_txnlist_find(info, txnid) != DB_NOTFOUND)
                        return ((dispatch_table[rectype])(logp,
                            db, lsnp, TXN_REDO, info));
@@ -188,14 +188,14 @@ int
 __db_txnlist_init(retp)
        void *retp;
 {
-       __db_txnhead *headp;
+       DB_TXNHEAD *headp;
 
-       if ((headp = (struct __db_txnhead *)
-           __db_malloc(sizeof(struct __db_txnhead))) == NULL)
+       if ((headp = (DB_TXNHEAD *)__db_malloc(sizeof(DB_TXNHEAD))) == NULL)
                return (ENOMEM);
 
        LIST_INIT(&headp->head);
        headp->maxid = 0;
+       headp->generation = 1;
 
        *(void **)retp = headp;
        return (0);
@@ -212,25 +212,26 @@ __db_txnlist_add(listp, txnid)
        void *listp;
        u_int32_t txnid;
 {
-       __db_txnhead *hp;
-       __db_txnlist *elp;
+       DB_TXNHEAD *hp;
+       DB_TXNLIST *elp;
 
-       if ((elp = (__db_txnlist *)__db_malloc(sizeof(__db_txnlist))) == NULL)
+       if ((elp = (DB_TXNLIST *)__db_malloc(sizeof(DB_TXNLIST))) == NULL)
                return (ENOMEM);
 
        elp->txnid = txnid;
-       hp = (struct __db_txnhead *)listp;
+       hp = (DB_TXNHEAD *)listp;
        LIST_INSERT_HEAD(&hp->head, elp, links);
        if (txnid > hp->maxid)
                hp->maxid = txnid;
+       elp->generation = hp->generation;
 
        return (0);
 }
 
 /*
  * __db_txnlist_find --
- *     Checks to see if txnid is in the txnid list, returns 1 if found,
- *     0 if not found.
+ *     Checks to see if a txnid with the current generation is in the
+ *     txnid list.
  *
  * PUBLIC: int __db_txnlist_find __P((void *, u_int32_t));
  */
@@ -239,45 +240,19 @@ __db_txnlist_find(listp, txnid)
        void *listp;
        u_int32_t txnid;
 {
-       __db_txnhead *hp;
-       __db_txnlist *p;
+       DB_TXNHEAD *hp;
+       DB_TXNLIST *p;
 
-       if ((hp = (struct __db_txnhead *)listp) == NULL)
+       if ((hp = (DB_TXNHEAD *)listp) == NULL)
                return (DB_NOTFOUND);
 
-       if (hp->maxid < txnid) {
-               hp->maxid = txnid;
-               return (DB_NOTFOUND);
-       }
-
        for (p = hp->head.lh_first; p != NULL; p = p->links.le_next)
-               if (p->txnid == txnid)
+               if (p->txnid == txnid && hp->generation == p->generation)
                        return (0);
 
        return (DB_NOTFOUND);
 }
 
-#ifdef DEBUG
-/*
- * __db_txnlist_print --
- *     Print out the transaction list.
- *
- * PUBLIC: void __db_txnlist_print __P((void *));
- */
-void
-__db_txnlist_print(listp)
-       void *listp;
-{
-       __db_txnhead *hp;
-       __db_txnlist *p;
-
-       hp = (struct __db_txnhead *)listp;
-       printf("Maxid: %lu\n", (u_long)hp->maxid);
-       for (p = hp->head.lh_first; p != NULL; p = p->links.le_next)
-               printf("TXNID: %lu\n", (u_long)p->txnid);
-}
-#endif
-
 /*
  * __db_txnlist_end --
  *     Discard transaction linked list.
@@ -288,13 +263,61 @@ void
 __db_txnlist_end(listp)
        void *listp;
 {
-       __db_txnhead *hp;
-       __db_txnlist *p;
+       DB_TXNHEAD *hp;
+       DB_TXNLIST *p;
 
-       hp = (struct __db_txnhead *)listp;
+       hp = (DB_TXNHEAD *)listp;
        while ((p = LIST_FIRST(&hp->head)) != LIST_END(&hp->head)) {
                LIST_REMOVE(p, links);
                __db_free(p);
        }
        __db_free(listp);
 }
+
+/*
+ * __db_txnlist_gen --
+ *     Change the current generation number.
+ *
+ * PUBLIC: void __db_txnlist_gen __P((void *, int));
+ */
+void
+__db_txnlist_gen(listp, incr)
+       void *listp;
+       int incr;
+{
+       DB_TXNHEAD *hp;
+
+       /*
+        * During recovery generation numbers keep track of how many "restart"
+        * checkpoints we've seen.  Restart checkpoints occur whenever we take
+        * a checkpoint and there are no outstanding transactions.  When that
+        * happens, we can reset transaction IDs back to 1.  It always happens
+        * at recovery and it prevents us from exhausting the transaction IDs
+        * name space.
+        */
+       hp = (DB_TXNHEAD *)listp;
+       hp->generation += incr;
+}
+
+#ifdef DEBUG
+/*
+ * __db_txnlist_print --
+ *     Print out the transaction list.
+ *
+ * PUBLIC: void __db_txnlist_print __P((void *));
+ */
+void
+__db_txnlist_print(listp)
+       void *listp;
+{
+       DB_TXNHEAD *hp;
+       DB_TXNLIST *p;
+
+       hp = (DB_TXNHEAD *)listp;
+       printf("Maxid: %lu Generation: %lu\n", (u_long)hp->maxid,
+           (u_long)hp->generation);
+       for (p = hp->head.lh_first; p != NULL; p = p->links.le_next)
+               printf("TXNID: %lu(%lu)\n", (u_long)p->txnid,
+               (u_long)p->generation);
+}
+#endif
index 59dfb85..6379fc1 100644 (file)
@@ -1,35 +1,27 @@
 /*-
  * See the file LICENSE for redistribution information.
  *
- * Copyright (c) 1996, 1997
+ * Copyright (c) 1996, 1997, 1998
  *     Sleepycat Software.  All rights reserved.
  */
 
 #include "config.h"
 
 #ifndef lint
-static const char sccsid[] = "@(#)db_dup.c     10.11 (Sleepycat) 1/8/98";
+static const char sccsid[] = "@(#)db_dup.c     10.18 (Sleepycat) 5/31/98";
 #endif /* not lint */
 
 #ifndef NO_SYSTEM_INCLUDES
 #include <sys/types.h>
-#include <sys/stat.h>
 
 #include <errno.h>
-#include <fcntl.h>
-#include <stddef.h>
-#include <stdio.h>
-#include <stdlib.h>
 #include <string.h>
-#include <unistd.h>
 #endif
 
 #include "db_int.h"
 #include "db_page.h"
-#include "db_swap.h"
 #include "btree.h"
 #include "db_am.h"
-#include "common_ext.h"
 
 static int __db_addpage __P((DB *,
     PAGE **, db_indx_t *, int (*)(DB *, u_int32_t, PAGE **)));
@@ -209,9 +201,8 @@ __db_dsplit(dbp, hp, indxp, size, newfunc)
        PAGE *h, *np, *tp;
        BKEYDATA *bk;
        DBT page_dbt;
-       db_indx_t indx, nindex, oindex, sum;
-       db_indx_t halfbytes, i, lastsum;
-       int did_indx, ret, s;
+       db_indx_t halfbytes, i, indx, lastsum, nindex, oindex, s, sum;
+       int did_indx, ret;
 
        h = *hp;
        indx = *indxp;
@@ -219,7 +210,7 @@ __db_dsplit(dbp, hp, indxp, size, newfunc)
        /* Create a temporary page to do compaction onto. */
        if ((tp = (PAGE *)__db_malloc(dbp->pgsize)) == NULL)
                return (ENOMEM);
-#ifdef DEBUG
+#ifdef DIAGNOSTIC
        memset(tp, 0xff, dbp->pgsize);
 #endif
        /* Create new page for the split. */
@@ -239,6 +230,7 @@ __db_dsplit(dbp, hp, indxp, size, newfunc)
        for (sum = 0, lastsum = 0, i = 0; i < NUM_ENT(h); i++) {
                if (i == indx) {
                        sum += size;
+                       did_indx = 1;
                        if (lastsum < halfbytes && sum >= halfbytes) {
                                /* We've crossed the halfway point. */
                                if ((db_indx_t)(halfbytes - lastsum) <
@@ -252,7 +244,6 @@ __db_dsplit(dbp, hp, indxp, size, newfunc)
                        }
                        *indxp = i;
                        lastsum = sum;
-                       did_indx = 1;
                }
                if (B_TYPE(GET_BKEYDATA(h, i)->type) == B_KEYDATA)
                        sum += BKEYDATA_SIZE(GET_BKEYDATA(h, i)->len);
index 8c6619f..d28740d 100644 (file)
@@ -1,7 +1,7 @@
 /*-
  * See the file LICENSE for redistribution information.
  *
- * Copyright (c) 1996, 1997
+ * Copyright (c) 1996, 1997, 1998
  *     Sleepycat Software.  All rights reserved.
  */
 /*
 #include "config.h"
 
 #ifndef lint
-static const char sccsid[] = "@(#)db_overflow.c        10.7 (Sleepycat) 11/2/97";
+static const char sccsid[] = "@(#)db_overflow.c        10.11 (Sleepycat) 5/7/98";
 #endif /* not lint */
 
 #ifndef NO_SYSTEM_INCLUDES
 #include <sys/types.h>
 
 #include <errno.h>
-#include <stdio.h>
-#include <stdlib.h>
 #include <string.h>
 #endif
 
 #include "db_int.h"
 #include "db_page.h"
 #include "db_am.h"
-#include "common_ext.h"
 
 /*
  * Big key/data code.
@@ -91,9 +88,9 @@ __db_goff(dbp, dbt, tlen, pgno, bpp, bpsz)
 {
        PAGE *h;
        db_indx_t bytes;
-       int ret;
        u_int32_t curoff, needed, start;
        u_int8_t *p, *src;
+       int ret;
 
        /*
         * Check if the buffer is big enough; if it is not and we are
@@ -259,13 +256,13 @@ __db_poff(dbp, dbt, pgnop, newfunc)
  * __db_ovref --
  *     Increment/decrement the reference count on an overflow page.
  *
- * PUBLIC: int __db_ovref __P((DB *, db_pgno_t, int));
+ * PUBLIC: int __db_ovref __P((DB *, db_pgno_t, int32_t));
  */
 int
 __db_ovref(dbp, pgno, adjust)
        DB *dbp;
        db_pgno_t pgno;
-       int adjust;
+       int32_t adjust;
 {
        PAGE *h;
        int ret;
@@ -277,7 +274,7 @@ __db_ovref(dbp, pgno, adjust)
 
        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, dbp->log_fileid, h->pgno, adjust,
                    &LSN(h))) != 0)
                        return (ret);
        OV_REF(h) += adjust;
@@ -353,8 +350,8 @@ __db_moff(dbp, dbt, pgno)
 {
        PAGE *pagep;
        u_int32_t cmp_bytes, key_left;
-       int ret;
        u_int8_t *p1, *p2;
+       int ret;
 
        /* While there are both keys to compare. */
        for (ret = 0, p1 = dbt->data,
index 1135a9e..a294cdd 100644 (file)
@@ -1,14 +1,14 @@
 /*-
  * See the file LICENSE for redistribution information.
  *
- * Copyright (c) 1996, 1997
+ * Copyright (c) 1996, 1997, 1998
  *     Sleepycat Software.  All rights reserved.
  */
 
 #include "config.h"
 
 #ifndef lint
-static const char sccsid[] = "@(#)db_pr.c      10.20 (Sleepycat) 1/8/98";
+static const char sccsid[] = "@(#)db_pr.c      10.29 (Sleepycat) 5/23/98";
 #endif /* not lint */
 
 #ifndef NO_SYSTEM_INCLUDES
@@ -16,7 +16,6 @@ static const char sccsid[] = "@(#)db_pr.c     10.20 (Sleepycat) 1/8/98";
 
 #include <ctype.h>
 #include <errno.h>
-#include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 #include <unistd.h>
@@ -160,7 +159,7 @@ __db_prdb(dbp)
        }
 
        fprintf(fp, "%s ", t);
-       __db_prflags(dbp->flags, fn);
+       __db_prflags(dbp->flags, fn, fp);
        fprintf(fp, "\n");
 
        return (0);
@@ -179,12 +178,16 @@ __db_prbtree(dbp)
        static const FN mfn[] = {
                { BTM_DUP,      "duplicates" },
                { BTM_RECNO,    "recno" },
+               { BTM_RECNUM,   "btree:records" },
+               { BTM_FIXEDLEN, "recno:fixed-length" },
+               { BTM_RENUMBER, "recno:renumber" },
                { 0 },
        };
        BTMETA *mp;
        BTREE *t;
        EPG *epg;
        FILE *fp;
+       PAGE *h;
        RECNO *rp;
        db_pgno_t i;
        int ret;
@@ -193,19 +196,29 @@ __db_prbtree(dbp)
        fp = __db_prinit(NULL);
 
        (void)fprintf(fp, "%s\nOn-page metadata:\n", DB_LINE);
-       i = PGNO_METADATA;
 
+       i = PGNO_METADATA;
        if ((ret = __bam_pget(dbp, (PAGE **)&mp, &i, 0)) != 0)
                return (ret);
 
        (void)fprintf(fp, "magic %#lx\n", (u_long)mp->magic);
-       (void)fprintf(fp, "version %lu\n", (u_long)mp->version);
+       (void)fprintf(fp, "version %#lx\n", (u_long)mp->version);
        (void)fprintf(fp, "pagesize %lu\n", (u_long)mp->pagesize);
        (void)fprintf(fp, "maxkey: %lu minkey: %lu\n",
            (u_long)mp->maxkey, (u_long)mp->minkey);
-       (void)fprintf(fp, "free %lu\n", (u_long)mp->free);
-       (void)fprintf(fp, "flags %lu", (u_long)mp->flags);
-       __db_prflags(mp->flags, mfn);
+
+       (void)fprintf(fp, "free %lu", (u_long)mp->free);
+       for (i = mp->free; i != PGNO_INVALID;) {
+               if ((ret = __bam_pget(dbp, &h, &i, 0)) != 0)
+                       return (ret);
+               i = h->next_pgno;
+               (void)memp_fput(dbp->mpf, h, 0);
+               (void)fprintf(fp, ", %lu", (u_long)i);
+       }
+       (void)fprintf(fp, "\n");
+
+       (void)fprintf(fp, "flags %#lx", (u_long)mp->flags);
+       __db_prflags(mp->flags, mfn, fp);
        (void)fprintf(fp, "\n");
        (void)memp_fput(dbp->mpf, mp, 0);
 
@@ -576,7 +589,7 @@ __db_isbad(h, die)
        BKEYDATA *bk;
        FILE *fp;
        db_indx_t i;
-       int type;
+       u_int type;
 
        fp = __db_prinit(NULL);
 
@@ -668,7 +681,8 @@ __db_pr(p, len)
        u_int32_t len;
 {
        FILE *fp;
-       int i, lastch;
+       u_int lastch;
+       int i;
 
        fp = __db_prinit(NULL);
 
@@ -681,7 +695,7 @@ __db_pr(p, len)
                        if (isprint(*p) || *p == '\n')
                                fprintf(fp, "%c", *p);
                        else
-                               fprintf(fp, "%#x", (u_int)*p);
+                               fprintf(fp, "0x%.2x", (u_int)*p);
                }
                if (len > 20) {
                        fprintf(fp, "...");
@@ -693,6 +707,50 @@ __db_pr(p, len)
 }
 
 /*
+ * __db_prdbt --
+ *     Print out a DBT data element.
+ *
+ * PUBLIC: int __db_prdbt __P((DBT *, int, FILE *));
+ */
+int
+__db_prdbt(dbtp, checkprint, fp)
+       DBT *dbtp;
+       int checkprint;
+       FILE *fp;
+{
+       static const char hex[] = "0123456789abcdef";
+       u_int8_t *p;
+       u_int32_t len;
+
+       /*
+        * !!!
+        * This routine is the routine that dumps out items in the format
+        * used by db_dump(1) and db_load(1).  This means that the format
+        * cannot change.
+        */
+       if (checkprint) {
+               for (len = dbtp->size, p = dbtp->data; len--; ++p)
+                       if (isprint(*p)) {
+                               if (*p == '\\' && fprintf(fp, "\\") != 1)
+                                       return (EIO);
+                               if (fprintf(fp, "%c", *p) != 1)
+                                       return (EIO);
+                       } else
+                               if (fprintf(fp, "\\%c%c",
+                                   hex[(u_int8_t)(*p & 0xf0) >> 4],
+                                   hex[*p & 0x0f]) != 3)
+                                       return (EIO);
+       } else
+               for (len = dbtp->size, p = dbtp->data; len--; ++p)
+                       if (fprintf(fp, "%c%c",
+                           hex[(u_int8_t)(*p & 0xf0) >> 4],
+                           hex[*p & 0x0f]) != 2)
+                               return (EIO);
+
+       return (fprintf(fp, "\n") == 1 ? 0 : EIO);
+}
+
+/*
  * __db_proff --
  *     Print out an off-page element.
  */
@@ -721,23 +779,21 @@ __db_proff(vp)
  * __db_prflags --
  *     Print out flags values.
  *
- * PUBLIC: void __db_prflags __P((u_int32_t, const FN *));
+ * PUBLIC: void __db_prflags __P((u_int32_t, const FN *, FILE *));
  */
 void
-__db_prflags(flags, fn)
+__db_prflags(flags, fn, fp)
        u_int32_t flags;
        FN const *fn;
-{
        FILE *fp;
+{
        const FN *fnp;
        int found;
        const char *sep;
 
-       fp = __db_prinit(NULL);
-
        sep = " (";
        for (found = 0, fnp = fn; fnp->mask != 0; ++fnp)
-               if (fnp->mask & flags) {
+               if (LF_ISSET(fnp->mask)) {
                        fprintf(fp, "%s%s", sep, fnp->name);
                        sep = ", ";
                        found = 1;
index 48e09e6..fe7c807 100644 (file)
@@ -1,30 +1,25 @@
 /*-
  * See the file LICENSE for redistribution information.
  *
- * Copyright (c) 1996, 1997
+ * Copyright (c) 1996, 1997, 1998
  *     Sleepycat Software.  All rights reserved.
  */
 
 #include "config.h"
 
 #ifndef lint
-static const char sccsid[] = "@(#)db_rec.c     10.12 (Sleepycat) 1/8/98";
+static const char sccsid[] = "@(#)db_rec.c     10.16 (Sleepycat) 4/28/98";
 #endif /* not lint */
 
 #ifndef NO_SYSTEM_INCLUDES
 #include <sys/types.h>
 
-#endif
-#include <ctype.h>
-#include <errno.h>
-#include <stddef.h>
-#include <stdlib.h>
 #include <string.h>
+#endif
 
 #include "db_int.h"
 #include "shqueue.h"
 #include "db_page.h"
-#include "db_dispatch.h"
 #include "log.h"
 #include "hash.h"
 #include "btree.h"
@@ -48,7 +43,8 @@ __db_addrem_recover(logp, dbtp, lsnp, redo, info)
        DB *file_dbp, *mdbp;
        DB_MPOOLFILE *mpf;
        PAGE *pagep;
-       int change, cmp_n, cmp_p, ret;
+       u_int32_t change;
+       int cmp_n, cmp_p, ret;
 
        REC_PRINT(__db_addrem_print);
        REC_INTRO(__db_addrem_read);
@@ -193,7 +189,8 @@ __db_big_recover(logp, dbtp, lsnp, redo, info)
        DB *file_dbp, *mdbp;
        DB_MPOOLFILE *mpf;
        PAGE *pagep;
-       int change, cmp_n, cmp_p, ret;
+       u_int32_t change;
+       int cmp_n, cmp_p, ret;
 
        REC_PRINT(__db_big_print);
        REC_INTRO(__db_big_read);
@@ -503,7 +500,8 @@ __db_addpage_recover(logp, dbtp, lsnp, redo, info)
        DB *file_dbp, *mdbp;
        DB_MPOOLFILE *mpf;
        PAGE *pagep;
-       int change, cmp_n, cmp_p, ret;
+       u_int32_t change;
+       int cmp_n, cmp_p, ret;
 
        REC_PRINT(__db_addpage_print);
        REC_INTRO(__db_addpage_read);
@@ -601,8 +599,7 @@ __db_debug_recover(logp, dbtp, lsnp, redo, info)
  * __db_noop_recover --
  *     Recovery function for noop.
  *
- * PUBLIC: int __db_noop_recover
- * PUBLIC:   __P((DB_LOG *, DBT *, DB_LSN *, int, void *));
+ * PUBLIC: int __db_noop_recover __P((DB_LOG *, DBT *, DB_LSN *, int, void *));
  */
 int
 __db_noop_recover(logp, dbtp, lsnp, redo, info)
@@ -613,16 +610,30 @@ __db_noop_recover(logp, dbtp, lsnp, redo, info)
        void *info;
 {
        __db_noop_args *argp;
-       int ret;
-
-       COMPQUIET(redo, 0);
-       COMPQUIET(logp, NULL);
+       DB *file_dbp, *mdbp;
+       DB_MPOOLFILE *mpf;
+       PAGE *pagep;
+       u_int32_t change;
+       int cmp_n, cmp_p, ret;
 
        REC_PRINT(__db_noop_print);
-       REC_NOOP_INTRO(__db_noop_read);
+       REC_INTRO(__db_noop_read);
+
+       if ((ret = memp_fget(mpf, &argp->pgno, 0, &pagep)) != 0)
+               goto out;
 
+       cmp_n = log_compare(lsnp, &LSN(pagep));
+       cmp_p = log_compare(&LSN(pagep), &argp->prevlsn);
+       change = 0;
+       if (cmp_p == 0 && redo) {
+               LSN(pagep) = *lsnp;
+               change = DB_MPOOL_DIRTY;
+       } else if (cmp_n == 0 && !redo) {
+               LSN(pagep) = argp->prevlsn;
+               change = DB_MPOOL_DIRTY;
+       }
        *lsnp = argp->prev_lsn;
-       ret = 0;
+       ret = memp_fput(mpf, pagep, change);
 
-       REC_NOOP_CLOSE;
+out:   REC_CLOSE;
 }
index 65441aa..9d9b599 100644 (file)
@@ -1,29 +1,26 @@
 /*-
  * See the file LICENSE for redistribution information.
  *
- * Copyright (c) 1996, 1997
+ * Copyright (c) 1996, 1997, 1998
  *     Sleepycat Software.  All rights reserved.
  */
 
 #include "config.h"
 
 #ifndef lint
-static const char sccsid[] = "@(#)db_ret.c     10.10 (Sleepycat) 11/28/97";
+static const char sccsid[] = "@(#)db_ret.c     10.13 (Sleepycat) 5/7/98";
 #endif /* not lint */
 
 #ifndef NO_SYSTEM_INCLUDES
 #include <sys/types.h>
 
 #include <errno.h>
-#include <stdio.h>
-#include <stdlib.h>
 #include <string.h>
 #endif
 
 #include "db_int.h"
 #include "db_page.h"
 #include "btree.h"
-#include "hash.h"
 #include "db_am.h"
 
 /*
index d908691..73e2a51 100644 (file)
@@ -1,27 +1,25 @@
 /*-
  * See the file LICENSE for redistribution information.
  *
- * Copyright (c) 1996, 1997
+ * Copyright (c) 1996, 1997, 1998
  *     Sleepycat Software.  All rights reserved.
  */
 
 #include "config.h"
 
 #ifndef lint
-static const char sccsid[] = "@(#)db_thread.c  8.13 (Sleepycat) 10/25/97";
+static const char sccsid[] = "@(#)db_thread.c  8.15 (Sleepycat) 4/26/98";
 #endif /* not lint */
 
 #ifndef NO_SYSTEM_INCLUDES
 #include <sys/types.h>
 
 #include <errno.h>
-#include <stdlib.h>
 #include <string.h>
 #endif
 
 #include "db_int.h"
 #include "db_page.h"
-#include "shqueue.h"
 #include "db_am.h"
 
 static int __db_getlockid __P((DB *, DB *));
index 7f6a16d..893dfa3 100644 (file)
@@ -1,7 +1,7 @@
 /*-
  * See the file LICENSE for redistribution information.
  *
- * Copyright (c) 1996, 1997
+ * Copyright (c) 1996, 1997, 1998
  *     Sleepycat Software.  All rights reserved.
  */
 
@@ -9,9 +9,9 @@
 
 #ifndef lint
 static const char copyright[] =
-"@(#) Copyright (c) 1997\n\
+"@(#) Copyright (c) 1996, 1997, 1998\n\
        Sleepycat Software Inc.  All rights reserved.\n";
-static const char sccsid[] = "@(#)db185.c      8.14 (Sleepycat) 10/25/97";
+static const char sccsid[] = "@(#)db185.c      8.17 (Sleepycat) 5/7/98";
 #endif
 
 #ifndef NO_SYSTEM_INCLUDES
@@ -20,7 +20,6 @@ static const char sccsid[] = "@(#)db185.c     8.14 (Sleepycat) 10/25/97";
 #include <errno.h>
 #include <fcntl.h>
 #include <stdlib.h>
-#include <stdio.h>
 #include <string.h>
 #include <unistd.h>
 #endif
@@ -114,6 +113,16 @@ __dbopen(file, oflags, mode, type, openinfo)
                 * and DB 2.0 doesn't.
                 *
                 * !!!
+                * Setting the file name to NULL specifies that we're creating
+                * a temporary backing file, in DB 2.X.  If we're opening the
+                * DB file read-only, change the flags to read-write, because
+                * temporary backing files cannot be opened read-only, and DB
+                * 2.X will return an error.  We are cheating here -- if the
+                * application does a put on the database, it will succeed --
+                * although that would be a stupid thing for the application
+                * to do.
+                *
+                * !!!
                 * Note, the file name in DB 1.85 was a const -- we don't do
                 * that in DB 2.0, so do that cast.
                 */
@@ -122,6 +131,10 @@ __dbopen(file, oflags, mode, type, openinfo)
                                (void)__os_close(__os_open(file, oflags, mode));
                        dbinfop->re_source = (char *)file;
                        file = NULL;
+
+                       if (O_RDONLY)
+                               oflags &= ~O_RDONLY;
+                       oflags |= O_RDWR;
                }
 
                if ((ri = openinfo) != NULL) {
@@ -181,15 +194,14 @@ __dbopen(file, oflags, mode, type, openinfo)
         * Store the returned pointer to the real DB 2.0 structure in the
         * internal pointer.  Ugly, but we're not going for pretty, here.
         */
-       if ((__set_errno(db_open(file,
-           type, __db_oflags(oflags), mode, NULL, dbinfop, &dbp))) != 0) {
+       if ((errno = db_open(file,
+           type, __db_oflags(oflags), mode, NULL, dbinfop, &dbp)) != 0) {
                __db_free(db185p);
                return (NULL);
        }
 
        /* Create the cursor used for sequential ops. */
-       if ((__set_errno(dbp->cursor(dbp, NULL, &((DB185 *)db185p)->dbc)))
-           != 0) {
+       if ((errno = dbp->cursor(dbp, NULL, &((DB185 *)db185p)->dbc)) != 0) {
                s_errno = errno;
                (void)dbp->close(dbp, 0);
                __db_free(db185p);
index f3e24b9..f7d7af5 100644 (file)
@@ -1,7 +1,7 @@
 /*-
  * See the file LICENSE for redistribution information.
  *
- * Copyright (c) 1997
+ * Copyright (c) 1997, 1998
  *     Sleepycat Software.  All rights reserved.
  */
 /*
@@ -40,7 +40,7 @@
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- *     @(#)db185_int.h 8.4 (Sleepycat) 7/27/97
+ *     @(#)db185_int.h 8.7 (Sleepycat) 4/10/98
  */
 
 #ifndef _DB185_H_
@@ -90,11 +90,11 @@ typedef struct __db185 {
 /* Structure used to pass parameters to the btree routines. */
 typedef struct {
 #define        R_DUP           0x01    /* duplicate keys */
-       u_long  flags;
-       u_int   cachesize;      /* bytes to cache */
-       int     maxkeypage;     /* maximum keys per page */
-       int     minkeypage;     /* minimum keys per page */
-       u_int   psize;          /* page size */
+       u_int32_t flags;
+       u_int32_t cachesize;    /* bytes to cache */
+       u_int32_t maxkeypage;   /* maximum keys per page */
+       u_int32_t minkeypage;   /* minimum keys per page */
+       u_int32_t psize;        /* page size */
        int     (*compare)      /* comparison function */
            __P((const DBT *, const DBT *));
        size_t  (*prefix)       /* prefix function */
@@ -104,10 +104,10 @@ typedef struct {
 
 /* Structure used to pass parameters to the hashing routines. */
 typedef struct {
-       u_int   bsize;          /* bucket size */
-       u_int   ffactor;        /* fill factor */
-       u_int   nelem;          /* number of elements */
-       u_int   cachesize;      /* bytes to cache */
+       u_int32_t bsize;        /* bucket size */
+       u_int32_t ffactor;      /* fill factor */
+       u_int32_t nelem;        /* number of elements */
+       u_int32_t cachesize;    /* bytes to cache */
        u_int32_t               /* hash function */
                (*hash) __P((const void *, size_t));
        int     lorder;         /* byte order */
@@ -118,9 +118,9 @@ typedef struct {
 #define        R_FIXEDLEN      0x01    /* fixed-length records */
 #define        R_NOKEY         0x02    /* key not required */
 #define        R_SNAPSHOT      0x04    /* snapshot the input */
-       u_long  flags;
-       u_int   cachesize;      /* bytes to cache */
-       u_int   psize;          /* page size */
+       u_int32_t flags;
+       u_int32_t cachesize;    /* bytes to cache */
+       u_int32_t psize;        /* page size */
        int     lorder;         /* byte order */
        size_t  reclen;         /* record length (fixed-length records) */
        u_char  bval;           /* delimiting byte (variable-length records */
index f3b02c7..0e1b878 100644 (file)
@@ -1,7 +1,7 @@
 /*-
  * See the file LICENSE for redistribution information.
  *
- * Copyright (c) 1996, 1997
+ * Copyright (c) 1996, 1997, 1998
  *     Sleepycat Software.  All rights reserved.
  */
 /*
@@ -36,7 +36,7 @@
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- *     @(#)db_185.h.src        8.5 (Sleepycat) 1/15/98
+ *     @(#)db_185.h.src        8.7 (Sleepycat) 4/10/98
  */
 
 #ifndef _DB_185_H_
@@ -127,11 +127,11 @@ typedef struct __db {
 /* Structure used to pass parameters to the btree routines. */
 typedef struct {
 #define        R_DUP           0x01    /* duplicate keys */
-       u_long  flags;
-       u_int   cachesize;      /* bytes to cache */
-       int     maxkeypage;     /* maximum keys per page */
-       int     minkeypage;     /* minimum keys per page */
-       u_int   psize;          /* page size */
+       u_int32_t flags;
+       u_int32_t cachesize;    /* bytes to cache */
+       u_int32_t maxkeypage;   /* maximum keys per page */
+       u_int32_t minkeypage;   /* minimum keys per page */
+       u_int32_t psize;        /* page size */
        int     (*compare)      /* comparison function */
            __P((const DBT *, const DBT *));
        size_t  (*prefix)       /* prefix function */
@@ -144,10 +144,10 @@ typedef struct {
 
 /* Structure used to pass parameters to the hashing routines. */
 typedef struct {
-       u_int   bsize;          /* bucket size */
-       u_int   ffactor;        /* fill factor */
-       u_int   nelem;          /* number of elements */
-       u_int   cachesize;      /* bytes to cache */
+       u_int32_t bsize;        /* bucket size */
+       u_int32_t ffactor;      /* fill factor */
+       u_int32_t nelem;        /* number of elements */
+       u_int32_t cachesize;    /* bytes to cache */
        u_int32_t               /* hash function */
                (*hash) __P((const void *, size_t));
        int     lorder;         /* byte order */
@@ -158,9 +158,9 @@ typedef struct {
 #define        R_FIXEDLEN      0x01    /* fixed-length records */
 #define        R_NOKEY         0x02    /* key not required */
 #define        R_SNAPSHOT      0x04    /* snapshot the input */
-       u_long  flags;
-       u_int   cachesize;      /* bytes to cache */
-       u_int   psize;          /* page size */
+       u_int32_t flags;
+       u_int32_t cachesize;    /* bytes to cache */
+       u_int32_t psize;        /* page size */
        int     lorder;         /* byte order */
        size_t  reclen;         /* record length (fixed-length records) */
        u_char  bval;           /* delimiting byte (variable-length records */
index eacd3f9..b48b104 100644 (file)
@@ -1,10 +1,10 @@
 /*-
  * See the file LICENSE for redistribution information.
  *
- * Copyright (c) 1996, 1997
+ * Copyright (c) 1996, 1997, 1998
  *     Sleepycat Software.  All rights reserved.
  *
- *     @(#)db_int.h.src        10.41 (Sleepycat) 1/8/98
+ *     @(#)db_int.h.src        10.62 (Sleepycat) 5/23/98
  */
 
 #ifndef _DB_INTERNAL_H_
@@ -12,8 +12,6 @@
 
 #include "db.h"                                /* Standard DB include file. */
 #include "queue.h"
-#include "os_func.h"
-#include "os_ext.h"
 
 /*******************************************************
  * General purpose constants and macros.
@@ -77,8 +75,8 @@
 #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
+/* Free and free-string macros that overwrite memory. */
+#ifdef DIAGNOSTIC
 #undef FREE
 #define        FREE(p, len) {                                                  \
        memset(p, 0xff, len);                                           \
@@ -117,36 +115,41 @@ typedef struct __fn {
 #undef DB_LINE
 #define        DB_LINE "=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-="
 
+/* Global variables. */
+typedef struct __db_globals {
+       int db_mutexlocks;              /* DB_MUTEXLOCKS */
+       int db_region_anon;             /* DB_REGION_ANON, DB_REGION_NAME */
+       int db_region_init;             /* DB_REGION_INIT */
+       int db_tsl_spins;               /* DB_TSL_SPINS */
+       int db_pageyield;               /* DB_PAGEYIELD */
+} DB_GLOBALS;
+extern DB_GLOBALS      __db_global_values;
+#define        DB_GLOBAL(v)    __db_global_values.v
+
 /* Unused, or not-used-yet variable.  "Shut that bloody compiler up!" */
 #define        COMPQUIET(n, v) (n) = (v)
 
+/*
+ * Win16 needs specific syntax on callback functions.  Nobody else cares.
+ */
+#ifndef        DB_CALLBACK
+#define        DB_CALLBACK     /* Nothing. */
+#endif
+
 /*******************************************************
  * Files.
  *******************************************************/
-#ifndef MAXPATHLEN             /* Maximum path length. */
-#ifdef PATH_MAX
-#define        MAXPATHLEN      PATH_MAX
-#else
+ /*
+  * We use 1024 as the maximum path length.  It's too hard to figure out what
+  * the real path length is, as it was traditionally stored in <sys/param.h>,
+  * and that file isn't always available.
+  */
+#undef MAXPATHLEN
 #define        MAXPATHLEN      1024
-#endif
-#endif
 
 #define        PATH_DOT        "."     /* Current working directory. */
 #define        PATH_SEPARATOR  "/"     /* Path separator character. */
 
-#ifndef S_IRUSR                        /* UNIX specific file permissions. */
-#define        S_IRUSR 0000400         /* R for owner */
-#define        S_IWUSR 0000200         /* W for owner */
-#define        S_IRGRP 0000040         /* R for group */
-#define        S_IWGRP 0000020         /* W for group */
-#define        S_IROTH 0000004         /* R for other */
-#define        S_IWOTH 0000002         /* W for other */
-#endif
-
-#ifndef S_ISDIR                        /* UNIX specific: directory test. */
-#define        S_ISDIR(m)      ((m & 0170000) == 0040000)
-#endif
-
 /*******************************************************
  * Mutex support.
  *******************************************************/
@@ -176,12 +179,12 @@ typedef unsigned char tsl_t;
 typedef struct _db_mutex_t {
 #ifdef HAVE_SPINLOCKS
        tsl_t     tsl_resource;         /* Resource test and set. */
-#ifdef DEBUG
-       u_long    pid;                  /* Lock holder: 0 or process pid. */
+#ifdef DIAGNOSTIC
+       u_int32_t pid;                  /* Lock holder: 0 or process pid. */
 #endif
 #else
        u_int32_t off;                  /* Backing file offset. */
-       u_long    pid;                  /* Lock holder: 0 or process pid. */
+       u_int32_t pid;                  /* Lock holder: 0 or process pid. */
 #endif
        u_int32_t spins;                /* Spins before block. */
        u_int32_t mutex_set_wait;       /* Granted after wait. */
@@ -195,11 +198,11 @@ 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) : 0)
+       if (F_ISSET(dbp, DB_AM_THREAD))                                 \
+           (void)__db_mutex_lock((db_mutex_t *)(dbp)->mutexp, -1);
 #define        DB_THREAD_UNLOCK(dbp)                                           \
-       (F_ISSET(dbp, DB_AM_THREAD) ?                                   \
-           __db_mutex_unlock((db_mutex_t *)(dbp)->mutexp, -1) : 0)
+       if (F_ISSET(dbp, DB_AM_THREAD))                                 \
+           (void)__db_mutex_unlock((db_mutex_t *)(dbp)->mutexp, -1);
 
 /* Btree/recno local statistics structure. */
 struct __db_bt_lstat;  typedef struct __db_bt_lstat DB_BTREE_LSTAT;
@@ -228,7 +231,7 @@ typedef enum {
 } APPNAME;
 
 /*******************************************************
- * Regions.
+ * Shared memory regions.
  *******************************************************/
 /*
  * The shared memory regions share an initial structure so that the general
@@ -240,16 +243,69 @@ typedef enum {
  */
 typedef struct _rlayout {
        db_mutex_t lock;                /* Region mutex. */
+#define        DB_REGIONMAGIC  0x120897
+       u_int32_t  valid;               /* Valid magic number. */
        u_int32_t  refcnt;              /* Region reference count. */
        size_t     size;                /* Region length. */
        int        majver;              /* Major version number. */
        int        minver;              /* Minor version number. */
        int        patch;               /* Patch version number. */
+#define        INVALID_SEGID   -1
+       int        segid;               /* shmget(2) ID, or Win16 segment ID. */
 
-#define        DB_R_DELETED    0x01            /* Region was deleted. */
+#define        REGION_ANONYMOUS        0x01    /* Region is/should be in anon mem. */
        u_int32_t  flags;
 } RLAYOUT;
 
+/*
+ * DB creates all regions on 4K boundaries out of sheer paranoia, so that
+ * we don't make the underlying VM unhappy.
+ */
+#define        DB_VMPAGESIZE   (4 * 1024)
+#define        DB_ROUNDOFF(i) {                                                \
+       (i) += DB_VMPAGESIZE - 1;                                       \
+       (i) -= (i) % DB_VMPAGESIZE;                                     \
+}
+
+/*
+ * The interface to region attach is nasty, there is a lot of complex stuff
+ * going on, which has to be retained between create/attach and detach.  The
+ * REGINFO structure keeps track of it.
+ */
+struct __db_reginfo;   typedef struct __db_reginfo REGINFO;
+struct __db_reginfo {
+                                       /* Arguments. */
+       DB_ENV     *dbenv;              /* Region naming info. */
+       APPNAME     appname;            /* Region naming info. */
+       char       *path;               /* Region naming info. */
+       const char *file;               /* Region naming info. */
+       int         mode;               /* Region mode, if a file. */
+       size_t      size;               /* Region size. */
+       u_int32_t   dbflags;            /* Region file open flags, if a file. */
+
+                                       /* Results. */
+       char       *name;               /* Region name. */
+       void       *addr;               /* Region address. */
+       int         fd;                 /* Fcntl(2) locking file descriptor.
+                                          NB: this is only valid if a regular
+                                          file is backing the shared region,
+                                          and mmap(2) is being used to map it
+                                          into our address space. */
+       int         segid;              /* shmget(2) ID, or Win16 segment ID. */
+
+                                       /* Shared flags. */
+/*                             0x0001  COMMON MASK with RLAYOUT structure. */
+#define        REGION_CANGROW          0x0002  /* Can grow. */
+#define        REGION_CREATED          0x0004  /* Created. */
+#define        REGION_HOLDINGSYS       0x0008  /* Holding system resources. */
+#define        REGION_LASTDETACH       0x0010  /* Delete on last detach. */
+#define        REGION_MALLOC           0x0020  /* Created in malloc'd memory. */
+#define        REGION_PRIVATE          0x0040  /* Private to thread/process. */
+#define        REGION_REMOVED          0x0080  /* Already deleted. */
+#define        REGION_SIZEDEF          0x0100  /* Use default region size if exists. */
+       u_int32_t   flags;
+};
+
 /*******************************************************
  * Mpool.
  *******************************************************/
@@ -281,7 +337,7 @@ typedef struct __dbpginfo {
 #define        DB_LOGGING(dbp)                                                 \
        (F_ISSET(dbp, DB_AM_LOGGING) && !F_ISSET(dbp, DB_AM_RECOVER))
 
-#ifdef DEBUG
+#ifdef DIAGNOSTIC
 /*
  * Debugging macro to log operations.
  *     If DEBUG_WOP is defined, log operations that modify the database.
@@ -318,7 +374,7 @@ typedef struct __dbpginfo {
 #else
 #define        DEBUG_LREAD(D, T, O, K, A, F)
 #define        DEBUG_LWRITE(D, T, O, K, A, F)
-#endif /* DEBUG */
+#endif /* DIAGNOSTIC */
 
 /*******************************************************
  * Transactions and recovery.
@@ -339,4 +395,8 @@ struct __db_txn {
        size_t          off;            /* Detail structure within region. */
        TAILQ_ENTRY(__db_txn) links;
 };
+
+#include "os_func.h"
+#include "os_ext.h"
+
 #endif /* !_DB_INTERNAL_H_ */
index 81f4bba..261fe81 100644 (file)
@@ -1,7 +1,7 @@
 /*-
  * See the file LICENSE for redistribution information.
  *
- * Copyright (c) 1996, 1997
+ * Copyright (c) 1996, 1997, 1998
  *     Sleepycat Software.  All rights reserved.
  */
 /*
 #include "config.h"
 
 #ifndef lint
-static const char sccsid[] = "@(#)dbm.c        10.10 (Sleepycat) 1/16/98";
+static const char sccsid[] = "@(#)dbm.c        10.16 (Sleepycat) 5/7/98";
 #endif /* not lint */
 
 #ifndef NO_SYSTEM_INCLUDES
-#include <sys/param.h>
+#include <sys/types.h>
 
 #include <errno.h>
 #include <fcntl.h>
-#include <stdio.h>
 #include <string.h>
 #endif
 
@@ -82,7 +81,7 @@ __db_dbm_init(file)
        if (__cur_db != NULL)
                (void)dbm_close(__cur_db);
        if ((__cur_db =
-           dbm_open(file, O_CREAT | O_RDWR, S_IRUSR | S_IWUSR)) != NULL)
+           dbm_open(file, O_CREAT | O_RDWR, __db_omode("rw----"))) != NULL)
                return (0);
        if ((__cur_db = dbm_open(file, O_RDONLY, 0)) != NULL)
                return (0);
@@ -244,19 +243,19 @@ __db_ndbm_fetch(db, key)
 {
        DBT _key, _data;
        datum data;
-       int status;
+       int ret;
 
        memset(&_key, 0, sizeof(DBT));
        memset(&_data, 0, sizeof(DBT));
        _key.size = key.dsize;
        _key.data = key.dptr;
-       status = db->get((DB *)db, NULL, &_key, &_data, 0);
-       if (status) {
-               data.dptr = NULL;
-               data.dsize = 0;
-       } else {
+       if ((ret = db->get((DB *)db, NULL, &_key, &_data, 0)) == 0) {
                data.dptr = _data.data;
                data.dsize = _data.size;
+       } else {
+               data.dptr = NULL;
+               data.dsize = 0;
+               __set_errno (ret == DB_NOTFOUND ? ENOENT : ret);
        }
        return (data);
 }
@@ -273,7 +272,7 @@ __db_ndbm_firstkey(db)
 {
        DBT _key, _data;
        datum key;
-       int status;
+       int ret;
 
        DBC *cp;
 
@@ -285,13 +284,13 @@ __db_ndbm_firstkey(db)
 
        memset(&_key, 0, sizeof(DBT));
        memset(&_data, 0, sizeof(DBT));
-       status = (cp->c_get)(cp, &_key, &_data, DB_FIRST);
-       if (status) {
-               key.dptr = NULL;
-               key.dsize = 0;
-       } else {
+       if ((ret = (cp->c_get)(cp, &_key, &_data, DB_FIRST)) == 0) {
                key.dptr = _key.data;
                key.dsize = _key.size;
+       } else {
+               key.dptr = NULL;
+               key.dsize = 0;
+               __set_errno (ret == DB_NOTFOUND ? ENOENT : ret);
        }
        return (key);
 }
@@ -309,7 +308,7 @@ __db_ndbm_nextkey(db)
        DBC *cp;
        DBT _key, _data;
        datum key;
-       int status;
+       int ret;
 
        if ((cp = TAILQ_FIRST(&db->curs_queue)) == NULL)
                if ((errno = db->cursor(db, NULL, &cp)) != 0) {
@@ -319,13 +318,13 @@ __db_ndbm_nextkey(db)
 
        memset(&_key, 0, sizeof(DBT));
        memset(&_data, 0, sizeof(DBT));
-       status = (cp->c_get)(cp, &_key, &_data, DB_NEXT);
-       if (status) {
-               key.dptr = NULL;
-               key.dsize = 0;
-       } else {
+       if ((ret = (cp->c_get)(cp, &_key, &_data, DB_NEXT)) == 0) {
                key.dptr = _key.data;
                key.dsize = _key.size;
+       } else {
+               key.dptr = NULL;
+               key.dsize = 0;
+               __set_errno (ret == DB_NOTFOUND ? ENOENT : ret);
        }
        return (key);
 }
@@ -347,14 +346,10 @@ __db_ndbm_delete(db, key)
        memset(&_key, 0, sizeof(DBT));
        _key.data = key.dptr;
        _key.size = key.dsize;
-       ret = (((DB *)db)->del)((DB *)db, NULL, &_key, 0);
-       if (ret < 0)
-               errno = ENOENT;
-       else if (ret > 0) {
-               errno = ret;
-               ret = -1;
-       }
-       return (ret);
+       if ((ret = (((DB *)db)->del)((DB *)db, NULL, &_key, 0)) == 0)
+               return (0);
+       errno = ret == DB_NOTFOUND ? ENOENT : ret;
+       return (-1);
 }
 weak_alias (__db_ndbm_delete, dbm_delete)
 
@@ -371,6 +366,7 @@ __db_ndbm_store(db, key, data, flags)
        int flags;
 {
        DBT _key, _data;
+       int ret;
 
        memset(&_key, 0, sizeof(DBT));
        memset(&_data, 0, sizeof(DBT));
@@ -378,8 +374,13 @@ __db_ndbm_store(db, key, data, flags)
        _key.size = key.dsize;
        _data.data = data.dptr;
        _data.size = data.dsize;
-       return (db->put((DB *)db,
-           NULL, &_key, &_data, (flags == DBM_INSERT) ? DB_NOOVERWRITE : 0));
+       if ((ret = db->put((DB *)db, NULL,
+           &_key, &_data, flags == DBM_INSERT ? DB_NOOVERWRITE : 0)) == 0)
+               return (0);
+       if (ret == DB_KEYEXIST)
+               return (1);
+       errno = ret;
+       return (-1);
 }
 weak_alias (__db_ndbm_store, dbm_store)
 
index 5193ece..5e0660b 100644 (file)
@@ -1,7 +1,7 @@
 /*-
  * See the file LICENSE for redistribution information.
  *
- * Copyright (c) 1996, 1997
+ * Copyright (c) 1996, 1997, 1998
  *     Sleepycat Software.  All rights reserved.
  */
 /*
 #include "config.h"
 
 #ifndef lint
-static const char sccsid[] = "@(#)hash.c       10.36 (Sleepycat) 1/8/98";
+static const char sccsid[] = "@(#)hash.c       10.45 (Sleepycat) 5/11/98";
 #endif /* not lint */
 
 #ifndef NO_SYSTEM_INCLUDES
 #include <sys/types.h>
-#include <sys/stat.h>
 
 #include <errno.h>
-#include <fcntl.h>
-#include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
-#include <unistd.h>
 #endif
 
-#include "shqueue.h"
 #include "db_int.h"
+#include "shqueue.h"
 #include "db_page.h"
 #include "db_am.h"
 #include "db_ext.h"
@@ -71,20 +67,20 @@ static const char sccsid[] = "@(#)hash.c    10.36 (Sleepycat) 1/8/98";
 #include "log.h"
 
 static int  __ham_c_close __P((DBC *));
-static int  __ham_c_del __P((DBC *, int));
-static int  __ham_c_get __P((DBC *, DBT *, DBT *, int));
-static int  __ham_c_put __P((DBC *, DBT *, DBT *, int));
+static int  __ham_c_del __P((DBC *, u_int32_t));
+static int  __ham_c_get __P((DBC *, DBT *, DBT *, u_int32_t));
+static int  __ham_c_put __P((DBC *, DBT *, DBT *, u_int32_t));
 static int  __ham_c_init __P((DB *, DB_TXN *, DBC **));
 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 *, u_int));
+static int  __ham_delete __P((DB *, DB_TXN *, DBT *, u_int32_t));
+static int  __ham_dup_return __P((HTAB *, HASH_CURSOR *, DBT *, u_int32_t));
+static int  __ham_get __P((DB *, DB_TXN *, DBT *, DBT *, u_int32_t));
+static void __ham_init_htab __P((HTAB *, u_int32_t, u_int32_t));
 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 *));
-static int  __ham_put __P((DB *, DB_TXN *, DBT *, DBT *, int));
-static int  __ham_sync __P((DB *, int));
+static int  __ham_put __P((DB *, DB_TXN *, DBT *, DBT *, u_int32_t));
+static int  __ham_sync __P((DB *, u_int32_t));
 
 /************************** INTERFACE ROUTINES ***************************/
 /* OPEN/CLOSE */
@@ -175,9 +171,9 @@ __ham_open(dbp, dbinfo)
                        goto out;
                }
 
-               hashp->hdr->ffactor =
-                   dbinfo != NULL && dbinfo->h_ffactor ? dbinfo->h_ffactor : 0;
-               __ham_init_htab(hashp, dbinfo != NULL ? dbinfo->h_nelem : 0);
+               __ham_init_htab(hashp,
+                   dbinfo != NULL ? dbinfo->h_nelem : 0,
+                   dbinfo != NULL ? dbinfo->h_ffactor : 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)
@@ -230,7 +226,7 @@ out:        (void)__ham_close(dbp);
 }
 
 /*
- * PUBLIC: int  __ham_close __P((DB *));
+ * PUBLIC: int __ham_close __P((DB *));
  */
 int
 __ham_close(dbp)
@@ -264,13 +260,14 @@ __ham_close(dbp)
  * Returns 0 on No Error
  */
 static void
-__ham_init_htab(hashp, nelem)
+__ham_init_htab(hashp, nelem, ffactor)
        HTAB *hashp;
-       u_int nelem;
+       u_int32_t nelem, ffactor;
 {
        int32_t l2, nbuckets;
 
-       hashp->hdr->nelem = 0;
+       memset(hashp->hdr, 0, sizeof(HASHHDR));
+       hashp->hdr->ffactor = ffactor;
        hashp->hdr->pagesize = hashp->dbp->pgsize;
        ZERO_LSN(hashp->hdr->lsn);
        hashp->hdr->magic = DB_HASHMAGIC;
@@ -287,8 +284,6 @@ __ham_init_htab(hashp, nelem)
 
        nbuckets = 1 << l2;
 
-       hashp->hdr->spares[l2] = 0;
-       hashp->hdr->spares[l2 + 1] = 0;
        hashp->hdr->ovfl_point = l2;
        hashp->hdr->last_freed = PGNO_INVALID;
 
@@ -310,7 +305,7 @@ __ham_init_htab(hashp, nelem)
 static int
 __ham_sync(dbp, flags)
        DB *dbp;
-       int flags;
+       u_int32_t flags;
 {
        int ret;
 
@@ -342,10 +337,9 @@ __ham_get(dbp, txn, key, data, flags)
        DB_TXN *txn;
        DBT *key;
        DBT *data;
-       int flags;
+       u_int32_t flags;
 {
        DB *ldbp;
-       DBC *cp;
        HTAB *hashp;
        HASH_CURSOR *hcp;
        int ret, t_ret;
@@ -362,7 +356,6 @@ __ham_get(dbp, txn, key, data, flags)
        hashp = (HTAB *)ldbp->internal;
        SET_LOCKER(ldbp, txn);
        GET_META(ldbp, hashp);
-       cp = TAILQ_FIRST(&ldbp->curs_queue);
 
        hashp->hash_accesses++;
        hcp = (HASH_CURSOR *)TAILQ_FIRST(&ldbp->curs_queue)->internal;
@@ -386,14 +379,14 @@ __ham_put(dbp, txn, key, data, flags)
        DB_TXN *txn;
        DBT *key;
        DBT *data;
-       int flags;
+       u_int32_t flags;
 {
        DB *ldbp;
-       HTAB *hashp;
-       HASH_CURSOR *hcp;
        DBT tmp_val, *myval;
-       int ret, t_ret;
+       HASH_CURSOR *hcp;
+       HTAB *hashp;
        u_int32_t nbytes;
+       int ret, t_ret;
 
        DEBUG_LWRITE(dbp, txn, "ham_put", key, data, flags);
        if ((ret = __db_putchk(dbp, key, data,
@@ -531,7 +524,7 @@ __ham_delete(dbp, txn, key, flags)
        DB *dbp;
        DB_TXN *txn;
        DBT *key;
-       int flags;
+       u_int32_t flags;
 {
        DB *ldbp;
        HTAB *hashp;
@@ -539,7 +532,8 @@ __ham_delete(dbp, txn, key, flags)
        int ret, t_ret;
 
        DEBUG_LWRITE(dbp, txn, "ham_delete", key, NULL, flags);
-       if ((ret = __db_delchk(dbp, flags, F_ISSET(dbp, DB_AM_RDONLY))) != 0)
+       if ((ret =
+           __db_delchk(dbp, key, flags, F_ISSET(dbp, DB_AM_RDONLY))) != 0)
                return (ret);
 
        ldbp = dbp;
@@ -639,12 +633,12 @@ __ham_c_iclose(dbp, dbc)
 static int
 __ham_c_del(cursor, flags)
        DBC *cursor;
-       int flags;
+       u_int32_t flags;
 {
        DB *ldbp;
-       HTAB *hashp;
        HASH_CURSOR *hcp;
        HASH_CURSOR save_curs;
+       HTAB *hashp;
        db_pgno_t ppgno, chg_pgno;
        int ret, t_ret;
 
@@ -756,7 +750,7 @@ __ham_c_del(cursor, flags)
 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;
+               ret = t_ret;
        if (ret != 0)
                *hcp = save_curs;
        RELEASE_META(hashp->dbp, hashp);
@@ -770,7 +764,7 @@ __ham_c_get(cursor, key, data, flags)
        DBC *cursor;
        DBT *key;
        DBT *data;
-       int flags;
+       u_int32_t flags;
 {
        DB *ldbp;
        HTAB *hashp;
@@ -805,7 +799,7 @@ __ham_c_get(cursor, key, data, flags)
                        ret = __ham_item_prev(hashp, hcp, DB_LOCK_READ);
                        break;
                }
-               /* FALL THROUGH */
+               /* FALLTHROUGH */
        case DB_LAST:
                ret = __ham_item_last(hashp, hcp, DB_LOCK_READ);
                break;
@@ -893,7 +887,7 @@ __ham_c_get(cursor, key, data, flags)
                }
        }
 out1:  if ((t_ret = __ham_item_done(hashp, hcp, 0)) != 0 && ret == 0)
-               t_ret = ret;
+               ret = t_ret;
 out:   if (ret)
                *hcp = save_curs;
        RELEASE_META(hashp->dbp, hashp);
@@ -907,17 +901,17 @@ __ham_c_put(cursor, key, data, flags)
        DBC *cursor;
        DBT *key;
        DBT *data;
-       int flags;
+       u_int32_t flags;
 {
        DB *ldbp;
-       HTAB *hashp;
        HASH_CURSOR *hcp, save_curs;
-       int ret, t_ret;
+       HTAB *hashp;
        u_int32_t nbytes;
+       int ret, t_ret;
 
        DEBUG_LWRITE(cursor->dbp, cursor->txn, "ham_c_put",
            flags == DB_KEYFIRST || flags == DB_KEYLAST ? key : NULL,
-           NULL, flags);
+           data, flags);
        ldbp = cursor->dbp;
        if (F_ISSET(cursor->dbp, DB_AM_THREAD) &&
            (ret = __db_gethandle(cursor->dbp, __ham_hdup, &ldbp)) != 0)
@@ -1087,14 +1081,14 @@ __ham_dup_return(hashp, hcp, val, flags)
        HTAB *hashp;
        HASH_CURSOR *hcp;
        DBT *val;
-       int flags;
+       u_int32_t flags;
 {
        PAGE *pp;
        DBT *myval, tmp_val;
        db_indx_t ndx;
        db_pgno_t pgno;
        u_int8_t *hk, type;
-       int indx, ret;
+       int ret;
        db_indx_t len;
 
        /* Check for duplicate and return the first one. */
@@ -1145,7 +1139,6 @@ __ham_dup_return(hashp, hcp, val, flags)
                        memcpy(&pgno, HOFFDUP_PGNO(P_ENTRY(hcp->pagep, ndx)),
                            sizeof(db_pgno_t));
                        if (flags == DB_LAST || flags == DB_PREV) {
-                               indx = (int)hcp->dndx;
                                if ((ret = __db_dend(hashp->dbp,
                                    pgno, &hcp->dpagep)) != 0)
                                        return (ret);
@@ -1451,14 +1444,15 @@ __ham_c_update(hcp, chg_pgno, len, add, is_dup)
  * __ham_hdup --
  *     This function gets called when we create a duplicate handle for a
  *     threaded DB.  It should create the private part of the DB structure.
+ *
  * PUBLIC: int  __ham_hdup __P((DB *, DB *));
  */
 int
 __ham_hdup(orig, new)
        DB *orig, *new;
 {
-       HTAB *hashp;
        DBC *curs;
+       HTAB *hashp;
        int ret;
 
        if ((hashp = (HTAB *)__db_malloc(sizeof(HTAB))) == NULL)
index 8cbcee7..8a51283 100644 (file)
@@ -1,7 +1,7 @@
 /*-
  * See the file LICENSE for redistribution information.
  *
- * Copyright (c) 1996, 1997
+ * Copyright (c) 1996, 1997, 1998
  *     Sleepycat Software.  All rights reserved.
  */
 /*
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- *     @(#)hash.src    10.2 (Sleepycat) 11/2/97
+ *     @(#)hash.src    10.3 (Sleepycat) 4/10/98
  */
 
-#include "config.h"
-
 /*
  * This is the source file used to create the logging functions for the
  * hash package.  Each access method (or set of routines wishing to register
index 830ea46..41b1ebe 100644 (file)
@@ -15,8 +15,6 @@
 #include "db_dispatch.h"
 #include "hash.h"
 #include "db_am.h"
-#include "common_ext.h"
-
 /*
  * PUBLIC: int __ham_insdel_log
  * PUBLIC:     __P((DB_LOG *, DB_TXN *, DB_LSN *, u_int32_t,
@@ -104,7 +102,7 @@ int __ham_insdel_log(logp, txnid, ret_lsnp, flags,
                memcpy(bp, data->data, data->size);
                bp += data->size;
        }
-#ifdef DEBUG
+#ifdef DIAGNOSTIC
        if ((u_int32_t)(bp - (u_int8_t *)logrec.data) != logrec.size)
                fprintf(stderr, "Error in log record length");
 #endif
@@ -120,22 +118,23 @@ int __ham_insdel_log(logp, txnid, ret_lsnp, flags,
  * PUBLIC:    __P((DB_LOG *, DBT *, DB_LSN *, int, void *));
  */
 int
-__ham_insdel_print(notused1, dbtp, lsnp, notused3, notused4)
+__ham_insdel_print(notused1, dbtp, lsnp, notused2, notused3)
        DB_LOG *notused1;
        DBT *dbtp;
        DB_LSN *lsnp;
-       int notused3;
-       void *notused4;
+       int notused2;
+       void *notused3;
 {
        __ham_insdel_args *argp;
        u_int32_t i;
-       int c, ret;
+       u_int ch;
+       int ret;
 
        i = 0;
-       c = 0;
+       ch = 0;
        notused1 = NULL;
-       notused3 = 0;
-       notused4 = NULL;
+       notused2 = 0;
+       notused3 = NULL;
 
        if ((ret = __ham_insdel_read(dbtp->data, &argp)) != 0)
                return (ret);
@@ -154,20 +153,20 @@ __ham_insdel_print(notused1, dbtp, lsnp, notused3, notused4)
            (u_long)argp->pagelsn.file, (u_long)argp->pagelsn.offset);
        printf("\tkey: ");
        for (i = 0; i < argp->key.size; i++) {
-               c = ((char *)argp->key.data)[i];
-               if (isprint(c) || c == 0xa)
-                       putchar(c);
+               ch = ((u_int8_t *)argp->key.data)[i];
+               if (isprint(ch) || ch == 0xa)
+                       putchar(ch);
                else
-                       printf("%#x ", c);
+                       printf("%#x ", ch);
        }
        printf("\n");
        printf("\tdata: ");
        for (i = 0; i < argp->data.size; i++) {
-               c = ((char *)argp->data.data)[i];
-               if (isprint(c) || c == 0xa)
-                       putchar(c);
+               ch = ((u_int8_t *)argp->data.data)[i];
+               if (isprint(ch) || ch == 0xa)
+                       putchar(ch);
                else
-                       printf("%#x ", c);
+                       printf("%#x ", ch);
        }
        printf("\n");
        printf("\n");
@@ -300,7 +299,7 @@ int __ham_newpage_log(logp, txnid, ret_lsnp, flags,
        else
                memset(bp, 0, sizeof(*nextlsn));
        bp += sizeof(*nextlsn);
-#ifdef DEBUG
+#ifdef DIAGNOSTIC
        if ((u_int32_t)(bp - (u_int8_t *)logrec.data) != logrec.size)
                fprintf(stderr, "Error in log record length");
 #endif
@@ -316,22 +315,23 @@ int __ham_newpage_log(logp, txnid, ret_lsnp, flags,
  * PUBLIC:    __P((DB_LOG *, DBT *, DB_LSN *, int, void *));
  */
 int
-__ham_newpage_print(notused1, dbtp, lsnp, notused3, notused4)
+__ham_newpage_print(notused1, dbtp, lsnp, notused2, notused3)
        DB_LOG *notused1;
        DBT *dbtp;
        DB_LSN *lsnp;
-       int notused3;
-       void *notused4;
+       int notused2;
+       void *notused3;
 {
        __ham_newpage_args *argp;
        u_int32_t i;
-       int c, ret;
+       u_int ch;
+       int ret;
 
        i = 0;
-       c = 0;
+       ch = 0;
        notused1 = NULL;
-       notused3 = 0;
-       notused4 = NULL;
+       notused2 = 0;
+       notused3 = NULL;
 
        if ((ret = __ham_newpage_read(dbtp->data, &argp)) != 0)
                return (ret);
@@ -462,7 +462,7 @@ int __ham_splitmeta_log(logp, txnid, ret_lsnp, flags,
        else
                memset(bp, 0, sizeof(*metalsn));
        bp += sizeof(*metalsn);
-#ifdef DEBUG
+#ifdef DIAGNOSTIC
        if ((u_int32_t)(bp - (u_int8_t *)logrec.data) != logrec.size)
                fprintf(stderr, "Error in log record length");
 #endif
@@ -478,22 +478,23 @@ int __ham_splitmeta_log(logp, txnid, ret_lsnp, flags,
  * PUBLIC:    __P((DB_LOG *, DBT *, DB_LSN *, int, void *));
  */
 int
-__ham_splitmeta_print(notused1, dbtp, lsnp, notused3, notused4)
+__ham_splitmeta_print(notused1, dbtp, lsnp, notused2, notused3)
        DB_LOG *notused1;
        DBT *dbtp;
        DB_LSN *lsnp;
-       int notused3;
-       void *notused4;
+       int notused2;
+       void *notused3;
 {
        __ham_splitmeta_args *argp;
        u_int32_t i;
-       int c, ret;
+       u_int ch;
+       int ret;
 
        i = 0;
-       c = 0;
+       ch = 0;
        notused1 = NULL;
-       notused3 = 0;
-       notused4 = NULL;
+       notused2 = 0;
+       notused3 = NULL;
 
        if ((ret = __ham_splitmeta_read(dbtp->data, &argp)) != 0)
                return (ret);
@@ -622,7 +623,7 @@ int __ham_splitdata_log(logp, txnid, ret_lsnp, flags,
        else
                memset(bp, 0, sizeof(*pagelsn));
        bp += sizeof(*pagelsn);
-#ifdef DEBUG
+#ifdef DIAGNOSTIC
        if ((u_int32_t)(bp - (u_int8_t *)logrec.data) != logrec.size)
                fprintf(stderr, "Error in log record length");
 #endif
@@ -638,22 +639,23 @@ int __ham_splitdata_log(logp, txnid, ret_lsnp, flags,
  * PUBLIC:    __P((DB_LOG *, DBT *, DB_LSN *, int, void *));
  */
 int
-__ham_splitdata_print(notused1, dbtp, lsnp, notused3, notused4)
+__ham_splitdata_print(notused1, dbtp, lsnp, notused2, notused3)
        DB_LOG *notused1;
        DBT *dbtp;
        DB_LSN *lsnp;
-       int notused3;
-       void *notused4;
+       int notused2;
+       void *notused3;
 {
        __ham_splitdata_args *argp;
        u_int32_t i;
-       int c, ret;
+       u_int ch;
+       int ret;
 
        i = 0;
-       c = 0;
+       ch = 0;
        notused1 = NULL;
-       notused3 = 0;
-       notused4 = NULL;
+       notused2 = 0;
+       notused3 = NULL;
 
        if ((ret = __ham_splitdata_read(dbtp->data, &argp)) != 0)
                return (ret);
@@ -669,11 +671,11 @@ __ham_splitdata_print(notused1, dbtp, lsnp, notused3, notused4)
        printf("\tpgno: %lu\n", (u_long)argp->pgno);
        printf("\tpageimage: ");
        for (i = 0; i < argp->pageimage.size; i++) {
-               c = ((char *)argp->pageimage.data)[i];
-               if (isprint(c) || c == 0xa)
-                       putchar(c);
+               ch = ((u_int8_t *)argp->pageimage.data)[i];
+               if (isprint(ch) || ch == 0xa)
+                       putchar(ch);
                else
-                       printf("%#x ", c);
+                       printf("%#x ", ch);
        }
        printf("\n");
        printf("\tpagelsn: [%lu][%lu]\n",
@@ -813,7 +815,7 @@ int __ham_replace_log(logp, txnid, ret_lsnp, flags,
        }
        memcpy(bp, &makedup, sizeof(makedup));
        bp += sizeof(makedup);
-#ifdef DEBUG
+#ifdef DIAGNOSTIC
        if ((u_int32_t)(bp - (u_int8_t *)logrec.data) != logrec.size)
                fprintf(stderr, "Error in log record length");
 #endif
@@ -829,22 +831,23 @@ int __ham_replace_log(logp, txnid, ret_lsnp, flags,
  * PUBLIC:    __P((DB_LOG *, DBT *, DB_LSN *, int, void *));
  */
 int
-__ham_replace_print(notused1, dbtp, lsnp, notused3, notused4)
+__ham_replace_print(notused1, dbtp, lsnp, notused2, notused3)
        DB_LOG *notused1;
        DBT *dbtp;
        DB_LSN *lsnp;
-       int notused3;
-       void *notused4;
+       int notused2;
+       void *notused3;
 {
        __ham_replace_args *argp;
        u_int32_t i;
-       int c, ret;
+       u_int ch;
+       int ret;
 
        i = 0;
-       c = 0;
+       ch = 0;
        notused1 = NULL;
-       notused3 = 0;
-       notused4 = NULL;
+       notused2 = 0;
+       notused3 = NULL;
 
        if ((ret = __ham_replace_read(dbtp->data, &argp)) != 0)
                return (ret);
@@ -863,20 +866,20 @@ __ham_replace_print(notused1, dbtp, lsnp, notused3, notused4)
        printf("\toff: %ld\n", (long)argp->off);
        printf("\tolditem: ");
        for (i = 0; i < argp->olditem.size; i++) {
-               c = ((char *)argp->olditem.data)[i];
-               if (isprint(c) || c == 0xa)
-                       putchar(c);
+               ch = ((u_int8_t *)argp->olditem.data)[i];
+               if (isprint(ch) || ch == 0xa)
+                       putchar(ch);
                else
-                       printf("%#x ", c);
+                       printf("%#x ", ch);
        }
        printf("\n");
        printf("\tnewitem: ");
        for (i = 0; i < argp->newitem.size; i++) {
-               c = ((char *)argp->newitem.data)[i];
-               if (isprint(c) || c == 0xa)
-                       putchar(c);
+               ch = ((u_int8_t *)argp->newitem.data)[i];
+               if (isprint(ch) || ch == 0xa)
+                       putchar(ch);
                else
-                       printf("%#x ", c);
+                       printf("%#x ", ch);
        }
        printf("\n");
        printf("\tmakedup: %lu\n", (u_long)argp->makedup);
@@ -1014,7 +1017,7 @@ int __ham_newpgno_log(logp, txnid, ret_lsnp, flags,
        else
                memset(bp, 0, sizeof(*metalsn));
        bp += sizeof(*metalsn);
-#ifdef DEBUG
+#ifdef DIAGNOSTIC
        if ((u_int32_t)(bp - (u_int8_t *)logrec.data) != logrec.size)
                fprintf(stderr, "Error in log record length");
 #endif
@@ -1030,22 +1033,23 @@ int __ham_newpgno_log(logp, txnid, ret_lsnp, flags,
  * PUBLIC:    __P((DB_LOG *, DBT *, DB_LSN *, int, void *));
  */
 int
-__ham_newpgno_print(notused1, dbtp, lsnp, notused3, notused4)
+__ham_newpgno_print(notused1, dbtp, lsnp, notused2, notused3)
        DB_LOG *notused1;
        DBT *dbtp;
        DB_LSN *lsnp;
-       int notused3;
-       void *notused4;
+       int notused2;
+       void *notused3;
 {
        __ham_newpgno_args *argp;
        u_int32_t i;
-       int c, ret;
+       u_int ch;
+       int ret;
 
        i = 0;
-       c = 0;
+       ch = 0;
        notused1 = NULL;
-       notused3 = 0;
-       notused4 = NULL;
+       notused2 = 0;
+       notused3 = NULL;
 
        if ((ret = __ham_newpgno_read(dbtp->data, &argp)) != 0)
                return (ret);
@@ -1182,7 +1186,7 @@ int __ham_ovfl_log(logp, txnid, ret_lsnp, flags,
        else
                memset(bp, 0, sizeof(*metalsn));
        bp += sizeof(*metalsn);
-#ifdef DEBUG
+#ifdef DIAGNOSTIC
        if ((u_int32_t)(bp - (u_int8_t *)logrec.data) != logrec.size)
                fprintf(stderr, "Error in log record length");
 #endif
@@ -1198,22 +1202,23 @@ int __ham_ovfl_log(logp, txnid, ret_lsnp, flags,
  * PUBLIC:    __P((DB_LOG *, DBT *, DB_LSN *, int, void *));
  */
 int
-__ham_ovfl_print(notused1, dbtp, lsnp, notused3, notused4)
+__ham_ovfl_print(notused1, dbtp, lsnp, notused2, notused3)
        DB_LOG *notused1;
        DBT *dbtp;
        DB_LSN *lsnp;
-       int notused3;
-       void *notused4;
+       int notused2;
+       void *notused3;
 {
        __ham_ovfl_args *argp;
        u_int32_t i;
-       int c, ret;
+       u_int ch;
+       int ret;
 
        i = 0;
-       c = 0;
+       ch = 0;
        notused1 = NULL;
-       notused3 = 0;
-       notused4 = NULL;
+       notused2 = 0;
+       notused3 = NULL;
 
        if ((ret = __ham_ovfl_read(dbtp->data, &argp)) != 0)
                return (ret);
@@ -1364,7 +1369,7 @@ int __ham_copypage_log(logp, txnid, ret_lsnp, flags,
                memcpy(bp, page->data, page->size);
                bp += page->size;
        }
-#ifdef DEBUG
+#ifdef DIAGNOSTIC
        if ((u_int32_t)(bp - (u_int8_t *)logrec.data) != logrec.size)
                fprintf(stderr, "Error in log record length");
 #endif
@@ -1380,22 +1385,23 @@ int __ham_copypage_log(logp, txnid, ret_lsnp, flags,
  * PUBLIC:    __P((DB_LOG *, DBT *, DB_LSN *, int, void *));
  */
 int
-__ham_copypage_print(notused1, dbtp, lsnp, notused3, notused4)
+__ham_copypage_print(notused1, dbtp, lsnp, notused2, notused3)
        DB_LOG *notused1;
        DBT *dbtp;
        DB_LSN *lsnp;
-       int notused3;
-       void *notused4;
+       int notused2;
+       void *notused3;
 {
        __ham_copypage_args *argp;
        u_int32_t i;
-       int c, ret;
+       u_int ch;
+       int ret;
 
        i = 0;
-       c = 0;
+       ch = 0;
        notused1 = NULL;
-       notused3 = 0;
-       notused4 = NULL;
+       notused2 = 0;
+       notused3 = NULL;
 
        if ((ret = __ham_copypage_read(dbtp->data, &argp)) != 0)
                return (ret);
@@ -1418,11 +1424,11 @@ __ham_copypage_print(notused1, dbtp, lsnp, notused3, notused4)
            (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);
+               ch = ((u_int8_t *)argp->page.data)[i];
+               if (isprint(ch) || ch == 0xa)
+                       putchar(ch);
                else
-                       printf("%#x ", c);
+                       printf("%#x ", ch);
        }
        printf("\n");
        printf("\n");
index 9cebe72..c6d0ba4 100644 (file)
@@ -1,13 +1,13 @@
 /*-
  * See the file LICENSE for redistribution information.
  *
- * Copyright (c) 1996, 1997
+ * Copyright (c) 1996, 1997, 1998
  *     Sleepycat Software.  All rights reserved.
  */
 #include "config.h"
 
 #ifndef lint
-static const char sccsid[] = "@(#)hash_conv.c  10.4 (Sleepycat) 9/15/97";
+static const char sccsid[] = "@(#)hash_conv.c  10.5 (Sleepycat) 4/10/98";
 #endif /* not lint */
 
 #ifndef NO_SYSTEM_INCLUDES
index 979ddd7..232906a 100644 (file)
@@ -1,7 +1,7 @@
 /*-
  * See the file LICENSE for redistribution information.
  *
- * Copyright (c) 1996, 1997
+ * Copyright (c) 1996, 1997, 1998
  *     Sleepycat Software.  All rights reserved.
  */
 /*
@@ -43,7 +43,7 @@
 #include "config.h"
 
 #ifndef lint
-static const char sccsid[] = "@(#)hash_debug.c 10.2 (Sleepycat) 6/21/97";
+static const char sccsid[] = "@(#)hash_debug.c 10.6 (Sleepycat) 5/7/98";
 #endif /* not lint */
 
 #ifdef DEBUG
@@ -60,9 +60,6 @@ static const char sccsid[] = "@(#)hash_debug.c        10.2 (Sleepycat) 6/21/97";
  */
 #ifndef NO_SYSTEM_INCLUDES
 #include <sys/types.h>
-
-#include <stdio.h>
-#include <string.h>
 #endif
 
 #include "db_int.h"
@@ -83,10 +80,9 @@ __ham_dump_bucket(hashp, bucket)
 {
        PAGE *p;
        db_pgno_t pgno;
-       int ret;
 
        for (pgno = BUCKET_TO_PAGE(hashp, bucket); pgno != PGNO_INVALID;) {
-               if ((ret = memp_fget(hashp->dbp->mpf, &pgno, 0, &p)) != 0)
+               if (memp_fget(hashp->dbp->mpf, &pgno, 0, &p) != 0)
                        break;
                (void)__db_prpage(p, 1);
                pgno = p->next_pgno;
index f8b0adb..ba248dd 100644 (file)
@@ -1,7 +1,7 @@
 /*-
  * See the file LICENSE for redistribution information.
  *
- * Copyright (c) 1996, 1997
+ * Copyright (c) 1996, 1997, 1998
  *     Sleepycat Software.  All rights reserved.
  */
 /*
@@ -42,7 +42,7 @@
 #include "config.h"
 
 #ifndef lint
-static const char sccsid[] = "@(#)hash_dup.c   10.10 (Sleepycat) 1/8/98";
+static const char sccsid[] = "@(#)hash_dup.c   10.14 (Sleepycat) 5/7/98";
 #endif /* not lint */
 
 /*
@@ -61,15 +61,11 @@ static const char sccsid[] = "@(#)hash_dup.c        10.10 (Sleepycat) 1/8/98";
 #ifndef NO_SYSTEM_INCLUDES
 #include <sys/types.h>
 
-#include <stdio.h>
-#include <stdlib.h>
 #include <string.h>
-#include <unistd.h>
 #endif
 
 #include "db_int.h"
 #include "db_page.h"
-#include "db_swap.h"
 #include "hash.h"
 
 static int __ham_check_move __P((HTAB *, HASH_CURSOR *, int32_t));
@@ -89,14 +85,14 @@ static int __ham_make_dup __P((const DBT *, DBT *d, void **, u_int32_t *));
  * Case 4: The element is large enough to push the duplicate set onto a
  *        separate page.
  *
- * PUBLIC: int __ham_add_dup __P((HTAB *, HASH_CURSOR *, DBT *, int));
+ * PUBLIC: int __ham_add_dup __P((HTAB *, HASH_CURSOR *, DBT *, u_int32_t));
  */
 int
 __ham_add_dup(hashp, hcp, nval, flags)
        HTAB *hashp;
        HASH_CURSOR *hcp;
        DBT *nval;
-       int flags;
+       u_int32_t flags;
 {
        DBT pval, tmp_val;
        u_int32_t del_len, new_size;
@@ -367,9 +363,9 @@ __ham_check_move(hashp, hcp, add_len)
        DB_LSN new_lsn;
        PAGE *next_pagep;
        db_pgno_t next_pgno;
-       int rectype, ret;
-       u_int32_t new_datalen, old_len;
+       u_int32_t new_datalen, old_len, rectype;
        u_int8_t *hk;
+       int ret;
 
        /*
         * Check if we can do whatever we need to on this page.  If not,
@@ -419,7 +415,8 @@ __ham_check_move(hashp, hcp, add_len)
                    (ret = __ham_put_page(hashp->dbp, next_pagep, 0)) != 0)
                        return (ret);
 
-               if ((ret = __ham_get_page(hashp->dbp, next_pgno, &next_pagep)) != 0)
+               if ((ret =
+                   __ham_get_page(hashp->dbp, next_pgno, &next_pagep)) != 0)
                        return (ret);
 
                if (P_FREESPACE(next_pagep) >= new_datalen)
index 1bf12c4..9131098 100644 (file)
@@ -1,7 +1,7 @@
 /*-
  * See the file LICENSE for redistribution information.
  *
- * Copyright (c) 1996, 1997
+ * Copyright (c) 1996, 1997, 1998
  *     Sleepycat Software.  All rights reserved.
  */
 /*
@@ -47,7 +47,7 @@
 #include "config.h"
 
 #ifndef lint
-static const char sccsid[] = "@(#)hash_func.c  10.7 (Sleepycat) 9/16/97";
+static const char sccsid[] = "@(#)hash_func.c  10.8 (Sleepycat) 4/10/98";
 #endif /* not lint */
 
 #ifndef NO_SYSTEM_INCLUDES
index 09a4a0c..ce692f2 100644 (file)
@@ -1,7 +1,7 @@
 /*-
  * See the file LICENSE for redistribution information.
  *
- * Copyright (c) 1996, 1997
+ * Copyright (c) 1996, 1997, 1998
  *     Sleepycat Software.  All rights reserved.
  */
 /*
@@ -47,7 +47,7 @@
 #include "config.h"
 
 #ifndef lint
-static const char sccsid[] = "@(#)hash_page.c  10.31 (Sleepycat) 1/8/98";
+static const char sccsid[] = "@(#)hash_page.c  10.40 (Sleepycat) 6/2/98";
 #endif /* not lint */
 
 /*
@@ -70,15 +70,11 @@ static const char sccsid[] = "@(#)hash_page.c       10.31 (Sleepycat) 1/8/98";
 #include <sys/types.h>
 
 #include <errno.h>
-#include <stdio.h>
-#include <stdlib.h>
 #include <string.h>
-#include <unistd.h>
 #endif
 
 #include "db_int.h"
 #include "db_page.h"
-#include "db_swap.h"
 #include "hash.h"
 
 static int __ham_lock_bucket __P((DB *, HASH_CURSOR *, db_lockmode_t));
@@ -266,6 +262,7 @@ __ham_item_last(hashp, cursorp, mode)
        F_SET(cursorp, H_OK);
        return (__ham_item_prev(hashp, cursorp, mode));
 }
+
 /*
  * PUBLIC: int __ham_item_first __P((HTAB *, HASH_CURSOR *, db_lockmode_t));
  */
@@ -285,8 +282,10 @@ __ham_item_first(hashp, cursorp, mode)
 }
 
 /*
- * Returns a pointer to key/data pair on a page.  In the case of bigkeys,
- * just returns the page number and index of the bigkey pointer pair.
+ * __ham_item_prev --
+ *     Returns a pointer to key/data pair on a page.  In the case of
+ *     bigkeys, just returns the page number and index of the bigkey
+ *     pointer pair.
  *
  * PUBLIC: int __ham_item_prev __P((HTAB *, HASH_CURSOR *, db_lockmode_t));
  */
@@ -487,12 +486,61 @@ __ham_putitem(p, dbt, type)
        NUM_ENT(p) += 1;
 }
 
+/*
+ * PUBLIC: void __ham_reputpair
+ * PUBLIC:    __P((PAGE *p, u_int32_t, u_int32_t, const DBT *, const DBT *));
+ *
+ * This is a special case to restore a key/data pair to its original
+ * location during recovery.  We are guaranteed that the pair fits
+ * on the page and is not the last pair on the page (because if it's
+ * the last pair, the normal insert works).
+ */
+void
+__ham_reputpair(p, psize, ndx, key, data)
+       PAGE *p;
+       u_int32_t psize, ndx;
+       const DBT *key, *data;
+{
+       db_indx_t i, movebytes, newbytes;
+       u_int8_t *from;
+
+       /* First shuffle the existing items up on the page.  */
+       movebytes =
+           (ndx == 0 ? psize : p->inp[H_DATAINDEX(ndx - 1)]) - HOFFSET(p);
+       newbytes = key->size + data->size;
+       from = (u_int8_t *)p + HOFFSET(p);
+       memmove(from - newbytes, from, movebytes);
+
+       /*
+        * Adjust the indices and move them up 2 spaces. Note that we
+        * have to check the exit condition inside the loop just in case
+        * we are dealing with index 0 (db_indx_t's are unsigned).
+        */
+       for (i = NUM_ENT(p) - 1; ; i-- ) {
+               p->inp[i + 2] = p->inp[i] - newbytes;
+               if (i == H_KEYINDEX(ndx))
+                       break;
+       }
+
+       /* Put the key and data on the page. */
+       p->inp[H_KEYINDEX(ndx)] =
+           (ndx == 0 ? psize : p->inp[H_DATAINDEX(ndx - 1)]) - key->size;
+       p->inp[H_DATAINDEX(ndx)] = p->inp[H_KEYINDEX(ndx)] - data->size;
+       memcpy(P_ENTRY(p, H_KEYINDEX(ndx)), key->data, key->size);
+       memcpy(P_ENTRY(p, H_DATAINDEX(ndx)), data->data, data->size);
+
+       /* Adjust page info. */
+       HOFFSET(p) -= newbytes;
+       NUM_ENT(p) += 2;
+}
+
 
 /*
  * 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.
+ *
+ * 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, reclaim_page)
@@ -648,8 +696,9 @@ __ham_del_pair(hashp, cursorp, reclaim_page)
                /*
                 * Cursor is advanced to the beginning of the next page.
                 */
-               cursorp->bndx = NDX_INVALID;
+               cursorp->bndx = 0;
                cursorp->pgno = PGNO(p);
+               F_SET(cursorp, H_DELETED);
                chg_pgno = PGNO(p);
                if ((ret = __ham_dirty_page(hashp, p)) != 0 ||
                    (ret = __ham_del_page(hashp->dbp, n_pagep)) != 0)
@@ -748,8 +797,8 @@ __ham_replpair(hashp, hcp, dbt, make_dup)
 {
        DBT old_dbt, tdata, tmp;
        DB_LSN  new_lsn;
+       int32_t change;                 /* XXX: Possible overflow. */
        u_int32_t len;
-       int32_t change;
        int is_big, ret, type;
        u_int8_t *beg, *dest, *end, *hk, *src;
 
@@ -789,7 +838,7 @@ __ham_replpair(hashp, hcp, dbt, make_dup)
                change += dbt->doff + dbt->dlen - len;
 
 
-       if (change > (int)P_FREESPACE(hcp->pagep) || is_big) {
+       if (change > (int32_t)P_FREESPACE(hcp->pagep) || is_big) {
                /*
                 * Case 3 -- two subcases.
                 * A. This is not really a partial operation, but an overwrite.
@@ -954,7 +1003,7 @@ __ham_split_page(hashp, obucket, nbucket)
        HTAB *hashp;
        u_int32_t obucket, nbucket;
 {
-       DBT key, val, page_dbt;
+       DBT key, page_dbt;
        DB_ENV *dbenv;
        DB_LSN new_lsn;
        PAGE **pp, *old_pagep, *temp_pagep, *new_pagep;
@@ -995,7 +1044,7 @@ __ham_split_page(hashp, obucket, nbucket)
 
        big_len = 0;
        big_buf = NULL;
-       val.flags = key.flags = 0;
+       key.flags = 0;
        while (temp_pagep != NULL) {
                for (n = 0; n < (db_indx_t)H_NUMPAIRS(temp_pagep); n++) {
                        if ((ret =
@@ -1103,8 +1152,8 @@ __ham_split_page(hashp, obucket, nbucket)
            ret == 0)
                ret = tret;
 
-err:   if (0) {
-               if (old_pagep != NULL)
+       if (0) {
+err:           if (old_pagep != NULL)
                        (void)__ham_put_page(hashp->dbp, old_pagep, 1);
                if (new_pagep != NULL)
                        (void)__ham_put_page(hashp->dbp, new_pagep, 1);
@@ -1121,8 +1170,8 @@ err:      if (0) {
  * to which we just added something.  This allows us to link overflow
  * pages and return the new page having correctly put the last page.
  *
- * PUBLIC: int __ham_add_el __P((HTAB *, HASH_CURSOR *, const DBT *, const DBT *,
- * PUBLIC:     int));
+ * PUBLIC: int __ham_add_el
+ * PUBLIC:    __P((HTAB *, HASH_CURSOR *, const DBT *, const DBT *, int));
  */
 int
 __ham_add_el(hashp, hcp, key, val, type)
@@ -1136,8 +1185,8 @@ __ham_add_el(hashp, hcp, key, val, type)
        DB_LSN new_lsn;
        HOFFPAGE doff, koff;
        db_pgno_t next_pgno;
-       u_int32_t data_size, key_size, pairsize;
-       int do_expand, is_keybig, is_databig, rectype, ret;
+       u_int32_t data_size, key_size, pairsize, rectype;
+       int do_expand, is_keybig, is_databig, ret;
        int key_type, data_type;
 
        do_expand = 0;
@@ -1268,13 +1317,14 @@ __ham_add_el(hashp, hcp, key, val, type)
  * another.  Works for all types of hash entries (H_OFFPAGE, H_KEYDATA,
  * H_DUPLICATE, H_OFFDUP).  Since we log splits at a high level, we
  * do not need to do any logging here.
- * PUBLIC: void __ham_copy_item __P((HTAB *, PAGE *, int, PAGE *));
+ *
+ * PUBLIC: void __ham_copy_item __P((HTAB *, PAGE *, u_int32_t, PAGE *));
  */
 void
 __ham_copy_item(hashp, src_page, src_ndx, dest_page)
        HTAB *hashp;
        PAGE *src_page;
-       int src_ndx;
+       u_int32_t src_ndx;
        PAGE *dest_page;
 {
        u_int32_t len;
@@ -1409,7 +1459,7 @@ __ham_del_page(dbp, pagep)
                LSN(pagep) = new_lsn;
        }
 
-#ifdef DEBUG
+#ifdef DIAGNOSTIC
        {
                db_pgno_t __pgno;
                DB_LSN __lsn;
@@ -1563,13 +1613,13 @@ __ham_overflow_page(dbp, type, pp)
 #ifdef DEBUG
 /*
  * PUBLIC: #ifdef DEBUG
- * PUBLIC: int __bucket_to_page __P((HTAB *, int));
+ * PUBLIC: db_pgno_t __bucket_to_page __P((HTAB *, db_pgno_t));
  * PUBLIC: #endif
  */
-int
+db_pgno_t
 __bucket_to_page(hashp, n)
        HTAB *hashp;
-       int n;
+       db_pgno_t n;
 {
        int ret_val;
 
@@ -1580,7 +1630,6 @@ __bucket_to_page(hashp, n)
 }
 #endif
 
-
 /*
  * Create a bunch of overflow pages at the current split point.
  * PUBLIC: void __ham_init_ovflpages __P((HTAB *));
@@ -1660,8 +1709,9 @@ __ham_get_cpage(hashp, hcp, mode)
  * Get a new page at the cursor, putting the last page if necessary.
  * If the flag is set to H_ISDUP, then we are talking about the
  * duplicate page, not the main page.
- * PUBLIC: int __ham_next_cpage __P((HTAB *, HASH_CURSOR *, db_pgno_t,
- * PUBLIC:     int, int));
+ *
+ * PUBLIC: int __ham_next_cpage
+ * PUBLIC:    __P((HTAB *, HASH_CURSOR *, db_pgno_t, int, u_int32_t));
  */
 int
 __ham_next_cpage(hashp, hcp, pgno, dirty, flags)
@@ -1669,22 +1719,22 @@ __ham_next_cpage(hashp, hcp, pgno, dirty, flags)
        HASH_CURSOR *hcp;
        db_pgno_t pgno;
        int dirty;
-       int flags;
+       u_int32_t flags;
 {
        PAGE *p;
        int ret;
 
-       if (flags & H_ISDUP && hcp->dpagep != NULL &&
+       if (LF_ISSET(H_ISDUP) && hcp->dpagep != NULL &&
            (ret = __ham_put_page(hashp->dbp, hcp->dpagep, dirty)) != 0)
                return (ret);
-       else if (!(flags & H_ISDUP) && hcp->pagep != NULL &&
+       else if (!LF_ISSET(H_ISDUP) && hcp->pagep != NULL &&
            (ret = __ham_put_page(hashp->dbp, hcp->pagep, dirty)) != 0)
                return (ret);
 
        if ((ret = __ham_get_page(hashp->dbp, pgno, &p)) != 0)
                return (ret);
 
-       if (flags & H_ISDUP) {
+       if (LF_ISSET(H_ISDUP)) {
                hcp->dpagep = p;
                hcp->dpgno = pgno;
                hcp->dndx = 0;
index 0950825..efaf61c 100644 (file)
@@ -1,7 +1,7 @@
 /*-
  * See the file LICENSE for redistribution information.
  *
- * Copyright (c) 1996, 1997
+ * Copyright (c) 1996, 1997, 1998
  *     Sleepycat Software.  All rights reserved.
  */
 /*
 #include "config.h"
 
 #ifndef lint
-static const char sccsid[] = "@(#)hash_rec.c   10.15 (Sleepycat) 12/4/97";
+static const char sccsid[] = "@(#)hash_rec.c   10.19 (Sleepycat) 5/23/98";
 #endif /* not lint */
 
 #ifndef NO_SYSTEM_INCLUDES
 #include <sys/types.h>
 
 #include <errno.h>
-#include <stdlib.h>
 #include <string.h>
 #endif
 
@@ -64,7 +63,6 @@ static const char sccsid[] = "@(#)hash_rec.c  10.15 (Sleepycat) 12/4/97";
 #include "hash.h"
 #include "btree.h"
 #include "log.h"
-#include "db_dispatch.h"
 #include "common_ext.h"
 
 /*
@@ -131,13 +129,23 @@ __ham_insdel_recover(logp, dbtp, lsnp, redo, info)
 
        if ((op == DELPAIR && cmp_n == 0 && !redo) ||
            (op == PUTPAIR && cmp_p == 0 && redo)) {
-               /* Need to redo a PUT or undo a delete. */
-               __ham_putitem(pagep, &argp->key,
-                   !redo || PAIR_ISKEYBIG(argp->opcode) ?
-                   H_OFFPAGE : H_KEYDATA);
-               __ham_putitem(pagep, &argp->data,
-                   !redo || PAIR_ISDATABIG(argp->opcode) ?
-                   H_OFFPAGE : H_KEYDATA);
+               /*
+                * Need to redo a PUT or undo a delete.  If we are undoing a
+                * delete, we've got to restore the item back to its original
+                * position.  That's a royal pain in the butt (because we do
+                * not store item lengths on the page), but there's no choice.
+                */
+               if (op != DELPAIR ||
+                   argp->ndx == (u_int32_t)H_NUMPAIRS(pagep)) {
+                       __ham_putitem(pagep, &argp->key,
+                           !redo || PAIR_ISKEYBIG(argp->opcode) ?
+                           H_OFFPAGE : H_KEYDATA);
+                       __ham_putitem(pagep, &argp->data,
+                           !redo || PAIR_ISDATABIG(argp->opcode) ?
+                           H_OFFPAGE : H_KEYDATA);
+               } else
+                       (void) __ham_reputpair(pagep, hashp->hdr->pagesize,
+                           argp->ndx, &argp->key, &argp->data);
 
                LSN(pagep) = redo ? *lsnp : argp->pagelsn;
                if ((ret = __ham_put_page(file_dbp, pagep, 1)) != 0)
@@ -453,7 +461,7 @@ __ham_newpgno_recover(logp, dbtp, lsnp, redo, info)
        DBT *dbtp;
        DB_LSN *lsnp;
        int redo;
-        void *info;
+       void *info;
 {
        __ham_newpgno_args *argp;
        DB *mdbp, *file_dbp;
@@ -574,7 +582,7 @@ __ham_splitmeta_recover(logp, dbtp, lsnp, redo, info)
        DBT *dbtp;
        DB_LSN *lsnp;
        int redo;
-        void *info;
+       void *info;
 {
        __ham_splitmeta_args *argp;
        DB *mdbp, *file_dbp;
@@ -649,7 +657,7 @@ __ham_splitdata_recover(logp, dbtp, lsnp, redo, info)
        DBT *dbtp;
        DB_LSN *lsnp;
        int redo;
-        void *info;
+       void *info;
 {
        __ham_splitdata_args *argp;
        DB *mdbp, *file_dbp;
index 99c6078..b57ca09 100644 (file)
@@ -1,14 +1,14 @@
 /*-
  * See the file LICENSE for redistribution information.
  *
- * Copyright (c) 1996, 1997
+ * Copyright (c) 1996, 1997, 1998
  *     Sleepycat Software.  All rights reserved.
  */
 
 #include "config.h"
 
 #ifndef lint
-static const char sccsid[] = "@(#)hash_stat.c  10.6 (Sleepycat) 7/2/97";
+static const char sccsid[] = "@(#)hash_stat.c  10.8 (Sleepycat) 4/26/98";
 #endif /* not lint */
 
 #ifndef NO_SYSTEM_INCLUDES
@@ -20,7 +20,6 @@ static const char sccsid[] = "@(#)hash_stat.c 10.6 (Sleepycat) 7/2/97";
 #include "db_int.h"
 #include "db_page.h"
 #include "hash.h"
-#include "common_ext.h"
 
 /*
  * __ham_stat --
index 878096b..1660d33 100644 (file)
@@ -1,7 +1,7 @@
 /*-
  * See the file LICENSE for redistribution information.
  *
- * Copyright (c) 1996, 1997
+ * Copyright (c) 1996, 1997, 1998
  *     Sleepycat Software.  All rights reserved.
  */
 /*
@@ -43,7 +43,7 @@
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- *     @(#)btree.h     10.17 (Sleepycat) 9/23/97
+ *     @(#)btree.h     10.21 (Sleepycat) 5/23/98
  */
 
 /* Forward structure declarations. */
@@ -103,28 +103,39 @@ struct __recno;           typedef struct __recno RECNO;
  * to return deleted entries.  To simplify both the mnemonic representation
  * and the code that checks for various cases, we construct a set of bitmasks.
  */
-#define        S_READ          0x0001          /* Read locks. */
-#define        S_WRITE         0x0002          /* Write locks. */
-
-#define        S_APPEND        0x0040          /* Append to the tree. */
-#define        S_DELNO         0x0080          /* Don't return deleted items. */
-#define        S_DUPFIRST      0x0100          /* Return first duplicate. */
-#define        S_DUPLAST       0x0200          /* Return last duplicate. */
-#define        S_EXACT         0x0400          /* Exact items only. */
-#define        S_PARENT        0x0800          /* Lock page pair. */
-
-#define        S_DELETE        (S_WRITE | S_DUPFIRST | S_DELNO | S_EXACT)
+#define        S_READ          0x00001         /* Read locks. */
+#define        S_WRITE         0x00002         /* Write locks. */
+
+#define        S_APPEND        0x00040         /* Append to the tree. */
+#define        S_DELNO         0x00080         /* Don't return deleted items. */
+#define        S_DUPFIRST      0x00100         /* Return first duplicate. */
+#define        S_DUPLAST       0x00200         /* Return last duplicate. */
+#define        S_EXACT         0x00400         /* Exact items only. */
+#define        S_PARENT        0x00800         /* Lock page pair. */
+#define        S_STACK         0x01000         /* Need a complete stack. */
+
+#define        S_DELETE        (S_WRITE | S_DUPFIRST | S_DELNO | S_EXACT | S_STACK)
 #define        S_FIND          (S_READ | S_DUPFIRST | S_DELNO)
-#define        S_INSERT        (S_WRITE | S_DUPLAST)
-#define        S_KEYFIRST      (S_WRITE | S_DUPFIRST)
-#define        S_KEYLAST       (S_WRITE | S_DUPLAST)
+#define        S_INSERT        (S_WRITE | S_DUPLAST | S_STACK)
+#define        S_KEYFIRST      (S_WRITE | S_DUPFIRST | S_STACK)
+#define        S_KEYLAST       (S_WRITE | S_DUPLAST | S_STACK)
 #define        S_WRPAIR        (S_WRITE | S_DUPLAST | S_PARENT)
 
 /*
+ * If doing insert search (including keyfirst or keylast operations) or a
+ * split search on behalf of an insert, it's okay to return the entry one
+ * past the end of the page.
+ */
+#define        PAST_END_OK(f)                                                  \
+       ((f) == S_INSERT ||                                             \
+       (f) == S_KEYFIRST || (f) == S_KEYLAST || (f) == S_WRPAIR)
+
+/*
  * Flags to __bam_iitem().
  */
-#define        BI_NEWKEY       0x01            /* New key. */
-#define        BI_DELETED      0x02            /* Key/data pair only placeholder. */
+#define        BI_DELETED      0x01            /* Key/data pair only placeholder. */
+#define        BI_DOINCR       0x02            /* Increment the record count. */
+#define        BI_NEWKEY       0x04            /* New key. */
 
 /*
  * Various routines pass around page references.  A page reference can be a
@@ -138,6 +149,21 @@ struct __epg {
 };
 
 /*
+ * All cursors are queued from the master DB structure.  Convert the user's
+ * DB reference to the master DB reference.  We lock the master DB mutex
+ * so that we can walk the cursor queue.  There's no race in accessing the
+ * cursors, because if we're modifying a page, we have a write lock on it,
+ * and therefore no other thread than the current one can have a cursor that
+ * references the page.
+ */
+#define        CURSOR_SETUP(dbp) {                                             \
+       (dbp) = (dbp)->master;                                          \
+       DB_THREAD_LOCK(dbp);                                            \
+}
+#define        CURSOR_TEARDOWN(dbp)                                            \
+       DB_THREAD_UNLOCK(dbp);
+
+/*
  * Btree cursor.
  *
  * Arguments passed to __bam_ca_replace().
index 9c34c8c..b8a1373 100644 (file)
@@ -2,7 +2,7 @@
 #ifndef _btree_ext_h_
 #define _btree_ext_h_
 int __bam_close __P((DB *));
-int __bam_sync __P((DB *, int));
+int __bam_sync __P((DB *, u_int32_t));
 int __bam_cmp __P((DB *, const DBT *, EPG *));
 int __bam_defcmp __P((const DBT *, const DBT *));
 size_t __bam_defpfx __P((const DBT *, const DBT *));
@@ -11,7 +11,7 @@ int __bam_pgout __P((db_pgno_t, void *, DBT *));
 int __bam_mswap __P((PAGE *));
 int __bam_cursor __P((DB *, DB_TXN *, DBC **));
 int __bam_c_iclose __P((DB *, DBC *));
-int __bam_get __P((DB *, DB_TXN *, DBT *, DBT *, int));
+int __bam_get __P((DB *, DB_TXN *, DBT *, DBT *, u_int32_t));
 int __bam_ovfl_chk __P((DB *, CURSOR *, u_int32_t, int));
 int __bam_cprint __P((DB *));
 int __bam_ca_delete __P((DB *, db_pgno_t, u_int32_t, CURSOR *, int));
@@ -23,8 +23,8 @@ void __bam_ca_replace
    __P((DB *, db_pgno_t, u_int32_t, ca_replace_arg));
 void __bam_ca_split __P((DB *,
    db_pgno_t, db_pgno_t, db_pgno_t, u_int32_t, int));
-int __bam_delete __P((DB *, DB_TXN *, DBT *, int));
-int __ram_delete __P((DB *, DB_TXN *, DBT *, int));
+int __bam_delete __P((DB *, DB_TXN *, DBT *, u_int32_t));
+int __ram_delete __P((DB *, DB_TXN *, DBT *, u_int32_t));
 int __bam_ditem __P((DB *, PAGE *, u_int32_t));
 int __bam_adjindx __P((DB *, PAGE *, u_int32_t, u_int32_t, int));
 int __bam_dpage __P((DB *, const DBT *));
@@ -35,10 +35,10 @@ int __bam_free __P((DB *, PAGE *));
 int __bam_lt __P((DB *));
 int __bam_lget __P((DB *, int, db_pgno_t, db_lockmode_t, DB_LOCK *));
 int __bam_lput __P((DB *, DB_LOCK));
-int __bam_pget __P((DB *, PAGE **, db_pgno_t *, int));
-int __bam_put __P((DB *, DB_TXN *, DBT *, DBT *, int));
+int __bam_pget __P((DB *, PAGE **, db_pgno_t *, u_int32_t));
+int __bam_put __P((DB *, DB_TXN *, DBT *, DBT *, u_int32_t));
 int __bam_iitem __P((DB *,
-   PAGE **, db_indx_t *, DBT *, DBT *, int, int));
+   PAGE **, db_indx_t *, DBT *, DBT *, u_int32_t, u_int32_t));
 int __bam_ritem __P((DB *, PAGE *, u_int32_t, DBT *));
 int __bam_pg_alloc_recover
   __P((DB_LOG *, DBT *, DB_LSN *, int, void *));
@@ -64,19 +64,19 @@ void __ram_ca __P((DB *, db_recno_t, ca_recno_arg));
 int __ram_cprint __P((DB *));
 int __ram_getno __P((DB *, const DBT *, db_recno_t *, int));
 int __ram_snapshot __P((DB *));
-int __bam_rsearch __P((DB *, db_recno_t *, u_int, int, int *));
-int __bam_adjust __P((DB *, BTREE *, int));
+int __bam_rsearch __P((DB *, db_recno_t *, u_int32_t, int, int *));
+int __bam_adjust __P((DB *, BTREE *, int32_t));
 int __bam_nrecs __P((DB *, db_recno_t *));
 db_recno_t __bam_total __P((PAGE *));
 int __bam_search __P((DB *,
-    const DBT *, u_int, int, db_recno_t *, int *));
+    const DBT *, u_int32_t, int, db_recno_t *, int *));
 int __bam_stkrel __P((DB *));
 int __bam_stkgrow __P((BTREE *));
 int __bam_split __P((DB *, void *));
 int __bam_broot __P((DB *, PAGE *, PAGE *, PAGE *));
 int __ram_root __P((DB *, PAGE *, PAGE *, PAGE *));
 int __bam_copy __P((DB *, PAGE *, PAGE *, u_int32_t, u_int32_t));
-int __bam_stat __P((DB *, void *, void *(*)(size_t), int));
+int __bam_stat __P((DB *, void *, void *(*)(size_t), u_int32_t));
 void __bam_add_mstat __P((DB_BTREE_LSTAT *, DB_BTREE_LSTAT *));
 int __bam_pg_alloc_log
     __P((DB_LOG *, DB_TXN *, DB_LSN *, u_int32_t,
index eb982bf..f5510a1 100644 (file)
@@ -53,9 +53,6 @@ int snprintf __P((char *, size_t, const char *, ...));
 int snprintf();
 #endif
 #endif
-#ifndef HAVE_STRDUP
-char *strdup __P((const char *));
-#endif
 #ifndef HAVE_STRERROR
 char *strerror __P((int));
 #endif
index b362c9c..4674f9c 100644 (file)
@@ -2,8 +2,8 @@
 #ifndef _common_ext_h_
 #define _common_ext_h_
 int __db_appname __P((DB_ENV *,
-   APPNAME, const char *, const char *, int *, char **));
-int __db_apprec __P((DB_ENV *, int));
+   APPNAME, const char *, const char *, u_int32_t, int *, char **));
+int __db_apprec __P((DB_ENV *, u_int32_t));
 int __db_byteorder __P((DB_ENV *, int));
 #ifdef __STDC__
 void __db_err __P((const DB_ENV *dbenv, const char *fmt, ...));
@@ -11,35 +11,32 @@ void __db_err __P((const DB_ENV *dbenv, const char *fmt, ...));
 void __db_err();
 #endif
 int __db_panic __P((DB *));
-int __db_fchk __P((DB_ENV *, const char *, int, int));
-int __db_fcchk __P((DB_ENV *, const char *, int, int, int));
-int __db_cdelchk __P((const DB *, int, int, int));
-int __db_cgetchk __P((const DB *, DBT *, DBT *, int, int));
+int __db_fchk __P((DB_ENV *, const char *, u_int32_t, u_int32_t));
+int __db_fcchk
+   __P((DB_ENV *, const char *, u_int32_t, u_int32_t, u_int32_t));
+int __db_cdelchk __P((const DB *, u_int32_t, int, int));
+int __db_cgetchk __P((const DB *, DBT *, DBT *, u_int32_t, int));
 int __db_cputchk __P((const DB *,
-   const DBT *, DBT *, int, int, int));
-int __db_delchk __P((const DB *, int, int));
-int __db_getchk __P((const DB *, const DBT *, DBT *, int));
-int __db_putchk __P((const DB *, DBT *, const DBT *, int, int, int));
-int __db_statchk __P((const DB *, int));
-int __db_syncchk __P((const DB *, int));
+   const DBT *, DBT *, u_int32_t, int, int));
+int __db_delchk __P((const DB *, DBT *, u_int32_t, int));
+int __db_getchk __P((const DB *, const DBT *, DBT *, u_int32_t));
+int __db_putchk
+   __P((const DB *, DBT *, const DBT *, u_int32_t, int, int));
+int __db_statchk __P((const DB *, u_int32_t));
+int __db_syncchk __P((const DB *, u_int32_t));
 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, 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 *));
-int __db_runlink __P((DB_ENV *,
-   APPNAME, const char *, const char *, int));
-int __db_rgrow __P((DB_ENV *, int, size_t));
-int __db_rremap __P((DB_ENV *, void *, size_t, size_t, int, void *));
+int __db_rattach __P((REGINFO *));
+int __db_rdetach __P((REGINFO *));
+int __db_runlink __P((REGINFO *, int));
+int __db_rgrow __P((REGINFO *, size_t));
+int __db_rreattach __P((REGINFO *, size_t));
 void __db_shalloc_init __P((void *, size_t));
 int __db_shalloc __P((void *, size_t, size_t, void *));
 void __db_shalloc_free __P((void *, void *));
 size_t __db_shalloc_count __P((void *));
 size_t __db_shsizeof __P((void *));
-void __db_shalloc_dump __P((FILE *, void *));
-int __db_tablesize __P((u_int));
-void __db_hashinit __P((void *, int));
+void __db_shalloc_dump __P((void *, FILE *));
+int __db_tablesize __P((u_int32_t));
+void __db_hashinit __P((void *, u_int32_t));
 #endif /* _common_ext_h_ */
index bf7a096..0a59de4 100644 (file)
@@ -1,10 +1,10 @@
 /*-
  * See the file LICENSE for redistribution information.
  *
- * Copyright (c) 1997
+ * Copyright (c) 1997, 1998
  *     Sleepycat Software.  All rights reserved.
  *
- *     @(#)cxx_int.h   10.4 (Sleepycat) 8/22/97
+ *     @(#)cxx_int.h   10.5 (Sleepycat) 4/10/98
  */
 
 #ifndef _CXX_INT_H_
index ebdaa27..97ad556 100644 (file)
@@ -1,10 +1,10 @@
 /*-
  * See the file LICENSE for redistribution information.
  *
- * Copyright (c) 1996, 1997
+ * Copyright (c) 1996, 1997, 1998
  *     Sleepycat Software.  All rights reserved.
  *
- *     @(#)db.h.src    10.102 (Sleepycat) 1/18/98
+ *     @(#)db.h.src    10.131 (Sleepycat) 6/2/98
  */
 
 #ifndef _DB_H_
@@ -54,8 +54,7 @@
  *
  * !!!
  * We also provide the standard u_int, u_long etc., if they're not provided
- * by the system.  This isn't completely necessary, but the example programs
- * need them.
+ * by the system.
  */
 #ifndef        __BIT_TYPES_DEFINED__
 #define        __BIT_TYPES_DEFINED__
@@ -72,9 +71,9 @@
 @u_long_decl@
 
 #define        DB_VERSION_MAJOR        2
-#define        DB_VERSION_MINOR        3
-#define        DB_VERSION_PATCH        16
-#define        DB_VERSION_STRING       "Sleepycat Software: DB 2.3.16: (1/19/98)"
+#define        DB_VERSION_MINOR        4
+#define        DB_VERSION_PATCH        14
+#define        DB_VERSION_STRING       "Sleepycat Software: DB 2.4.14: (6/2/98)"
 
 typedef        u_int32_t       db_pgno_t;      /* Page number type. */
 typedef        u_int16_t       db_indx_t;      /* Page offset type. */
@@ -95,6 +94,7 @@ struct __db_bt_stat;  typedef struct __db_bt_stat DB_BTREE_STAT;
 struct __db_dbt;       typedef struct __db_dbt DBT;
 struct __db_env;       typedef struct __db_env DB_ENV;
 struct __db_info;      typedef struct __db_info DB_INFO;
+struct __db_lock_stat; typedef struct __db_lock_stat DB_LOCK_STAT;
 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;
@@ -102,6 +102,7 @@ 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_finfo;typedef struct __db_mpool_finfo DB_MPOOL_FINFO;
 struct __db_mpool_fstat;typedef struct __db_mpool_fstat DB_MPOOL_FSTAT;
 struct __db_mpool_stat;        typedef struct __db_mpool_stat DB_MPOOL_STAT;
 struct __db_mpoolfile; typedef struct __db_mpoolfile DB_MPOOLFILE;
@@ -134,7 +135,7 @@ struct __db_dbt {
  * There are a set of functions that the application can replace with its
  * own versions, and some other knobs which can be turned at run-time.
  */
-#define        DB_FUNC_CALLOC   1              /* ANSI C calloc. */
+#define        DB_FUNC_CALLOC   1      /* DELETED: 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. */
@@ -149,12 +150,18 @@ struct __db_dbt {
 #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              /* DB: strdup(3). */
+#define        DB_FUNC_STRDUP  16      /* DELETED: DB: strdup(3). */
 #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. */
 #define        DB_TSL_SPINS    21              /* DB: initialize spin count. */
+#define        DB_FUNC_RUNLINK 22              /* DB: remove a shared region. */
+#define        DB_REGION_ANON  23              /* DB: anonymous, unnamed regions. */
+#define        DB_REGION_INIT  24              /* DB: page-fault regions in create. */
+#define        DB_REGION_NAME  25              /* DB: anonymous, named regions. */
+#define        DB_MUTEXLOCKS   26              /* DB: turn off all mutex locks. */
+#define        DB_PAGEYIELD    27              /* DB: yield the CPU on pool get. */
 
 /*
  * Database configuration and initialization.
@@ -162,52 +169,51 @@ struct __db_dbt {
  /*
   * Flags understood by both db_open(3) and db_appinit(3).
   */
-#define        DB_CREATE               0x00001 /* O_CREAT: create file as necessary. */
-#define        DB_NOMMAP               0x00002 /* Don't mmap underlying file. */
-#define        DB_THREAD               0x00004 /* Free-thread DB package handles. */
+#define        DB_CREATE             0x000001  /* O_CREAT: create file as necessary. */
+#define        DB_NOMMAP             0x000002  /* Don't mmap underlying file. */
+#define        DB_THREAD             0x000004  /* Free-thread DB package handles. */
 
 /*
  * Flags understood by db_appinit(3).
- *
- * DB_MUTEXDEBUG is internal only, and not documented.
  */
-/*                             0x00007    COMMON MASK. */
-#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. */
+/*                           0x000007     COMMON MASK. */
+#define        DB_INIT_LOCK          0x000008  /* Initialize locking. */
+#define        DB_INIT_LOG           0x000010  /* Initialize logging. */
+#define        DB_INIT_MPOOL         0x000020  /* Initialize mpool. */
+#define        DB_INIT_TXN           0x000040  /* Initialize transactions. */
+#define        DB_MPOOL_PRIVATE      0x000080  /* Mpool: private memory pool. */
+#define        __UNUSED_100          0x000100
+#define        DB_RECOVER            0x000200  /* Run normal recovery. */
+#define        DB_RECOVER_FATAL      0x000400  /* Run catastrophic recovery. */
+#define        DB_TXN_NOSYNC         0x000800  /* Do not sync log on commit. */
+#define        DB_USE_ENVIRON        0x001000  /* Use the environment. */
+#define        DB_USE_ENVIRON_ROOT   0x002000  /* Use the environment if root. */
 
 /* CURRENTLY UNUSED LOCK FLAGS. */
-#define        DB_TXN_LOCK_2PL         0x00000 /* Two-phase locking. */
-#define        DB_TXN_LOCK_OPTIMISTIC  0x00000 /* Optimistic locking. */
-#define        DB_TXN_LOCK_MASK        0x00000 /* Lock flags mask. */
+#define        DB_TXN_LOCK_2PL       0x000000  /* Two-phase locking. */
+#define        DB_TXN_LOCK_OPTIMIST  0x000000  /* Optimistic locking. */
+#define        DB_TXN_LOCK_MASK      0x000000  /* Lock flags mask. */
 
 /* CURRENTLY UNUSED LOG FLAGS. */
-#define        DB_TXN_LOG_REDO         0x00000 /* Redo-only logging. */
-#define        DB_TXN_LOG_UNDO         0x00000 /* Undo-only logging. */
-#define        DB_TXN_LOG_UNDOREDO     0x00000 /* Undo/redo write-ahead logging. */
-#define        DB_TXN_LOG_MASK         0x00000 /* Log flags mask. */
+#define        DB_TXN_LOG_REDO       0x000000  /* Redo-only logging. */
+#define        DB_TXN_LOG_UNDO       0x000000  /* Undo-only logging. */
+#define        DB_TXN_LOG_UNDOREDO   0x000000  /* Undo/redo write-ahead logging. */
+#define        DB_TXN_LOG_MASK       0x000000  /* Log flags mask. */
 
 /*
  * Flags understood by db_open(3).
  *
- * DB_EXCL and DB_TEMPORARY are internal only, and not documented.
- * DB_SEQUENTIAL is currently internal, but likely to be exported some day.
+ * DB_EXCL and DB_TEMPORARY are internal only, and are not documented.
+ * DB_SEQUENTIAL is currently internal, but may be exported some day.
  */
-/*                             0x00007    COMMON MASK. */
-/*                             0x07fff    ALREADY USED. */
-#define        DB_EXCL                 0x08000 /* O_EXCL: exclusive open. */
-#define        DB_RDONLY               0x10000 /* O_RDONLY: read-only. */
-#define        DB_SEQUENTIAL           0x20000 /* Indicate sequential access. */
-#define        DB_TEMPORARY            0x40000 /* Remove on last close. */
-#define        DB_TRUNCATE             0x80000 /* O_TRUNCATE: replace existing DB. */
+/*                           0x000007     COMMON MASK. */
+/*                           0x003fff     ALREADY USED. */
+#define        __UNUSED_4000         0x004000
+#define        DB_EXCL               0x008000  /* O_EXCL: exclusive open. */
+#define        DB_RDONLY             0x010000  /* O_RDONLY: read-only. */
+#define        DB_SEQUENTIAL         0x020000  /* Indicate sequential access. */
+#define        DB_TEMPORARY          0x040000  /* Remove on last close. */
+#define        DB_TRUNCATE           0x080000  /* O_TRUNCATE: replace existing DB. */
 
 /*
  * Deadlock detector modes; used in the DBENV structure to configure the
@@ -240,9 +246,9 @@ struct __db_env {
        /* Locking. */
        DB_LOCKTAB      *lk_info;       /* Return from lock_open(). */
        u_int8_t        *lk_conflicts;  /* Two dimensional conflict matrix. */
-       int              lk_modes;      /* Number of lock modes in table. */
-       u_int            lk_max;        /* Maximum number of locks. */
-       u_int32_t        lk_detect;     /* Deadlock detect on every conflict. */
+       u_int32_t        lk_modes;      /* Number of lock modes in table. */
+       u_int32_t        lk_max;        /* Maximum number of locks. */
+       u_int32_t        lk_detect;     /* Deadlock detect on all conflicts. */
 
        /* Logging. */
        DB_LOG          *lg_info;       /* Return from log_open(). */
@@ -255,7 +261,7 @@ struct __db_env {
 
        /* Transactions. */
        DB_TXNMGR       *tx_info;       /* Return from txn_open(). */
-       unsigned int     tx_max;        /* Maximum number of transactions. */
+       u_int32_t        tx_max;        /* Maximum number of transactions. */
        int (*tx_recover)               /* Dispatch function for recovery. */
            __P((DB_LOG *, DBT *, DB_LSN *, int, void *));
 
@@ -300,17 +306,17 @@ struct __db_info {
        void *(*db_malloc) __P((size_t));
 
        /* Btree access method. */
-       int              bt_maxkey;     /* Maximum keys per page. */
-       int              bt_minkey;     /* Minimum keys per page. */
+       u_int32_t        bt_maxkey;     /* Maximum keys per page. */
+       u_int32_t        bt_minkey;     /* Minimum keys per page. */
        int (*bt_compare)               /* Comparison function. */
            __P((const DBT *, const DBT *));
        size_t (*bt_prefix)             /* Prefix function. */
            __P((const DBT *, const DBT *));
 
        /* Hash access method. */
-       unsigned int     h_ffactor;     /* Fill factor. */
-       unsigned int     h_nelem;       /* Number of elements. */
-       u_int32_t       (*h_hash)       /* Hash function. */
+       u_int32_t        h_ffactor;     /* Fill factor. */
+       u_int32_t        h_nelem;       /* Number of elements. */
+       u_int32_t      (*h_hash)        /* Hash function. */
            __P((const void *, u_int32_t));
 
        /* Recno access method. */
@@ -353,6 +359,7 @@ struct __db_info {
 #define        DB_SET          0x010000        /* c_get(), log_get() */
 #define        DB_SET_RANGE    0x020000        /* c_get() */
 #define        DB_SET_RECNO    0x040000        /* c_get() */
+#define        DB_CURLSN       0x080000        /* log_put() */
 
 /*
  * DB (user visible) error return codes.
@@ -435,14 +442,14 @@ struct __db {
        void *(*db_malloc) __P((size_t));
 
                                        /* Functions. */
-       int (*close)    __P((DB *, int));
+       int (*close)    __P((DB *, u_int32_t));
        int (*cursor)   __P((DB *, DB_TXN *, DBC **));
-       int (*del)      __P((DB *, DB_TXN *, DBT *, int));
+       int (*del)      __P((DB *, DB_TXN *, DBT *, u_int32_t));
        int (*fd)       __P((DB *, int *));
-       int (*get)      __P((DB *, DB_TXN *, DBT *, DBT *, int));
-       int (*put)      __P((DB *, DB_TXN *, DBT *, DBT *, int));
-       int (*stat)     __P((DB *, void *, void *(*)(size_t), int));
-       int (*sync)     __P((DB *, int));
+       int (*get)      __P((DB *, DB_TXN *, DBT *, DBT *, u_int32_t));
+       int (*put)      __P((DB *, DB_TXN *, DBT *, DBT *, u_int32_t));
+       int (*stat)     __P((DB *, void *, void *(*)(size_t), u_int32_t));
+       int (*sync)     __P((DB *, u_int32_t));
 
 #define        DB_AM_DUP       0x000001        /* DB_DUP (internal). */
 #define        DB_AM_INMEM     0x000002        /* In-memory; no sync on close. */
@@ -483,9 +490,9 @@ struct __dbc {
        void     *internal;             /* Access method private. */
 
        int (*c_close)  __P((DBC *));
-       int (*c_del)    __P((DBC *, int));
-       int (*c_get)    __P((DBC *, DBT *, DBT *, int));
-       int (*c_put)    __P((DBC *, DBT *, DBT *, int));
+       int (*c_del)    __P((DBC *, u_int32_t));
+       int (*c_get)    __P((DBC *, DBT *, DBT *, u_int32_t));
+       int (*c_put)    __P((DBC *, DBT *, DBT *, u_int32_t));
 };
 
 /* Btree/recno statistics structure. */
@@ -524,10 +531,11 @@ struct __db_bt_stat {
 #if defined(__cplusplus)
 extern "C" {
 #endif
-int   db_appinit __P((const char *, char * const *, DB_ENV *, int));
+int   db_appinit __P((const char *, char * const *, DB_ENV *, u_int32_t));
 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 **));
+int   db_open __P((const char *,
+         DBTYPE, u_int32_t, int, DB_ENV *, DB_INFO *, DB **));
 int   db_value_set __P((int, int));
 char *db_version __P((int *, int *, int *));
 #if defined(__cplusplus)
@@ -575,6 +583,21 @@ typedef enum {
        DB_LOCK_IWR                     /* Intent to read and write. */
 } db_lockmode_t;
 
+/*
+ * Status of a lock.
+ */
+typedef enum {
+       DB_LSTAT_ABORTED,               /* Lock belongs to an aborted txn. */
+       DB_LSTAT_ERR,                   /* Lock is bad. */
+       DB_LSTAT_FREE,                  /* Lock is unallocated. */
+       DB_LSTAT_HELD,                  /* Lock is currently held. */
+       DB_LSTAT_NOGRANT,               /* Lock was not granted. */
+       DB_LSTAT_PENDING,               /* Lock was waiting and has been
+                                        * promoted; waiting for the owner
+                                        * to run and upgrade it to held. */
+       DB_LSTAT_WAITING                /* Lock is on the wait queue. */
+} db_status_t;
+
 /* Lock request structure. */
 struct __db_lockreq {
        db_lockop_t      op;            /* Operation. */
@@ -596,19 +619,38 @@ extern const u_int8_t db_rw_conflicts[];
 #define        DB_LOCK_RIW_N   6
 extern const u_int8_t db_riw_conflicts[];
 
+struct __db_lock_stat {
+       u_int32_t st_magic;             /* Lock file magic number. */
+       u_int32_t st_version;           /* Lock file version number. */
+       u_int32_t st_maxlocks;          /* Maximum number of locks in table. */
+       u_int32_t st_nmodes;            /* Number of lock modes. */
+       u_int32_t st_numobjs;           /* Number of objects. */
+       u_int32_t st_nlockers;          /* Number of lockers. */
+       u_int32_t st_nconflicts;        /* Number of lock conflicts. */
+       u_int32_t st_nrequests;         /* Number of lock gets. */
+       u_int32_t st_nreleases;         /* Number of lock puts. */
+       u_int32_t st_ndeadlocks;        /* Number of lock deadlocks. */
+       u_int32_t st_region_wait;       /* Region lock granted after wait. */
+       u_int32_t st_region_nowait;     /* Region lock granted without wait. */
+       u_int32_t st_refcnt;            /* Region reference count. */
+       u_int32_t st_regsize;           /* Region size. */
+};
+
 #if defined(__cplusplus)
 extern "C" {
 #endif
 int      lock_close __P((DB_LOCKTAB *));
-int      lock_detect __P((DB_LOCKTAB *, int, int));
+int      lock_detect __P((DB_LOCKTAB *, u_int32_t, u_int32_t));
 int      lock_get __P((DB_LOCKTAB *,
-           u_int32_t, int, const DBT *, db_lockmode_t, DB_LOCK *));
+           u_int32_t, u_int32_t, const DBT *, db_lockmode_t, DB_LOCK *));
 int      lock_id __P((DB_LOCKTAB *, u_int32_t *));
-int      lock_open __P((const char *, int, int, DB_ENV *, DB_LOCKTAB **));
+int      lock_open __P((const char *,
+           u_int32_t, int, DB_ENV *, DB_LOCKTAB **));
 int      lock_put __P((DB_LOCKTAB *, DB_LOCK));
+int      lock_stat __P((DB_LOCKTAB *, DB_LOCK_STAT **, void *(*)(size_t)));
 int      lock_unlink __P((const char *, int, DB_ENV *));
 int      lock_vec __P((DB_LOCKTAB *,
-           u_int32_t, int, DB_LOCKREQ *, int, DB_LOCKREQ **));
+           u_int32_t, u_int32_t, DB_LOCKREQ *, int, DB_LOCKREQ **));
 #if defined(__cplusplus)
 }
 #endif
@@ -651,19 +693,21 @@ struct __db_log_stat {
        u_int32_t st_region_nowait;     /* Region lock granted without wait. */
        u_int32_t st_cur_file;          /* Current log file number. */
        u_int32_t st_cur_offset;        /* Current log file offset. */
+       u_int32_t st_refcnt;            /* Region reference count. */
+       u_int32_t st_regsize;           /* Region size. */
 };
 
 #if defined(__cplusplus)
 extern "C" {
 #endif
-int     log_archive __P((DB_LOG *, char **[], int, void *(*)(size_t)));
+int     log_archive __P((DB_LOG *, char **[], u_int32_t, void *(*)(size_t)));
 int     log_close __P((DB_LOG *));
 int     log_compare __P((const DB_LSN *, const DB_LSN *));
 int     log_file __P((DB_LOG *, const DB_LSN *, char *, size_t));
 int     log_flush __P((DB_LOG *, const DB_LSN *));
-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_get __P((DB_LOG *, DB_LSN *, DBT *, u_int32_t));
+int     log_open __P((const char *, u_int32_t, int, DB_ENV *, DB_LOG **));
+int     log_put __P((DB_LOG *, DB_LSN *, const DBT *, u_int32_t));
 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 *));
@@ -705,6 +749,17 @@ struct __db_mpool_stat {
        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. */
+       u_int32_t st_refcnt;            /* Region reference count. */
+       u_int32_t st_regsize;           /* Region size. */
+};
+
+/* Mpool file open information structure. */
+struct __db_mpool_finfo {
+       int        ftype;               /* File type. */
+       DBT       *pgcookie;            /* Byte-string passed to pgin/pgout. */
+       u_int8_t  *fileid;              /* Unique file ID. */
+       int32_t    lsn_offset;          /* LSN offset in page. */
+       u_int32_t  clear_len;           /* Cleared length on created pages. */
 };
 
 /* Mpool file statistics structure. */
@@ -724,13 +779,13 @@ extern "C" {
 #endif
 int    memp_close __P((DB_MPOOL *));
 int    memp_fclose __P((DB_MPOOLFILE *));
-int    memp_fget __P((DB_MPOOLFILE *, db_pgno_t *, int, void *));
+int    memp_fget __P((DB_MPOOLFILE *, db_pgno_t *, u_int32_t, void *));
 int    memp_fopen __P((DB_MPOOL *, const char *,
-           int, int, int, size_t, int, DBT *, u_int8_t *, DB_MPOOLFILE **));
-int    memp_fput __P((DB_MPOOLFILE *, void *, int));
-int    memp_fset __P((DB_MPOOLFILE *, void *, int));
+           u_int32_t, int, size_t, DB_MPOOL_FINFO *, DB_MPOOLFILE **));
+int    memp_fput __P((DB_MPOOLFILE *, void *, u_int32_t));
+int    memp_fset __P((DB_MPOOLFILE *, void *, u_int32_t));
 int    memp_fsync __P((DB_MPOOLFILE *));
-int    memp_open __P((const char *, int, int, DB_ENV *, DB_MPOOL **));
+int    memp_open __P((const char *, u_int32_t, int, DB_ENV *, DB_MPOOL **));
 int    memp_register __P((DB_MPOOL *, int,
            int (*)(db_pgno_t, void *, DBT *),
            int (*)(db_pgno_t, void *, DBT *)));
@@ -765,16 +820,21 @@ struct __db_txn_active {
 };
 
 struct __db_txn_stat {
-       DB_LSN          st_last_ckp;    /* lsn of the last checkpoint */
-       DB_LSN          st_pending_ckp; /* last checkpoint did not finish */
-       time_t          st_time_ckp;    /* time of last checkpoint */
-       u_int32_t       st_last_txnid;  /* last transaction id given out */
-       u_int32_t       st_maxtxns;     /* maximum number of active txns */
-       u_int32_t       st_naborts;     /* number of aborted transactions */
-       u_int32_t       st_nbegins;     /* number of begun transactions */
-       u_int32_t       st_ncommits;    /* number of committed transactions */
-       u_int32_t       st_nactive;     /* number of active transactions */
-       DB_TXN_ACTIVE   *st_txnarray;   /* array of active transactions */
+       DB_LSN    st_last_ckp;          /* lsn of the last checkpoint */
+       DB_LSN    st_pending_ckp;       /* last checkpoint did not finish */
+       time_t    st_time_ckp;          /* time of last checkpoint */
+       u_int32_t st_last_txnid;        /* last transaction id given out */
+       u_int32_t st_maxtxns;   /* maximum number of active txns */
+       u_int32_t st_naborts;   /* number of aborted transactions */
+       u_int32_t st_nbegins;   /* number of begun transactions */
+       u_int32_t st_ncommits;  /* number of committed transactions */
+       u_int32_t st_nactive;   /* number of active transactions */
+       DB_TXN_ACTIVE
+                *st_txnarray;  /* array of active transactions */
+       u_int32_t st_region_wait;       /* Region lock granted after wait. */
+       u_int32_t st_region_nowait;     /* Region lock granted without wait. */
+       u_int32_t st_refcnt;            /* Region reference count. */
+       u_int32_t st_regsize;           /* Region size. */
 };
 
 #if defined(__cplusplus)
@@ -782,11 +842,11 @@ extern "C" {
 #endif
 int      txn_abort __P((DB_TXN *));
 int      txn_begin __P((DB_TXNMGR *, DB_TXN *, DB_TXN **));
-int      txn_checkpoint __P((const DB_TXNMGR *, int, int));
+int      txn_checkpoint __P((const DB_TXNMGR *, u_int32_t, u_int32_t));
 int      txn_commit __P((DB_TXN *));
 int      txn_close __P((DB_TXNMGR *));
 u_int32_t txn_id __P((DB_TXN *));
-int      txn_open __P((const char *, int, int, DB_ENV *, DB_TXNMGR **));
+int      txn_open __P((const char *, u_int32_t, int, DB_ENV *, DB_TXNMGR **));
 int      txn_prepare __P((DB_TXN *));
 int      txn_stat __P((DB_TXNMGR *, DB_TXN_STAT **, void *(*)(size_t)));
 int      txn_unlink __P((const char *, int, DB_ENV *));
@@ -810,10 +870,17 @@ int         txn_unlink __P((const char *, int, DB_ENV *));
  */
 #define        DBM_SUFFIX      ".db"
 
+#if defined(_XPG4_2)
+typedef struct {
+       char *dptr;
+       size_t dsize;
+} datum;
+#else
 typedef struct {
        char *dptr;
        int dsize;
 } datum;
+#endif
 
 /*
  * Translate DBM calls into DB calls so that DB doesn't step on the
@@ -894,7 +961,7 @@ typedef enum {
 
 typedef struct entry {
        char *key;
-       void *data;
+       char *data;
 } ENTRY;
 
 /*
@@ -909,7 +976,7 @@ typedef struct entry {
 #if defined(__cplusplus)
 extern "C" {
 #endif
-int     __db_hcreate __P((unsigned int));
+int     __db_hcreate __P((size_t));
 void    __db_hdestroy __P((void));
 ENTRY  *__db_hsearch __P((ENTRY, ACTION));
 #if defined(__cplusplus)
index a88eb4e..a928ca8 100644 (file)
@@ -1,7 +1,7 @@
 /*-
  * See the file LICENSE for redistribution information.
  *
- * Copyright (c) 1996, 1997
+ * Copyright (c) 1996, 1997, 1998
  *     Sleepycat Software.  All rights reserved.
  */
 /*
@@ -36,7 +36,7 @@
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- *     @(#)db_185.h.src        8.5 (Sleepycat) 1/15/98
+ *     @(#)db_185.h.src        8.7 (Sleepycat) 4/10/98
  */
 
 #ifndef _DB_185_H_
@@ -127,11 +127,11 @@ typedef struct __db {
 /* Structure used to pass parameters to the btree routines. */
 typedef struct {
 #define        R_DUP           0x01    /* duplicate keys */
-       u_long  flags;
-       u_int   cachesize;      /* bytes to cache */
-       int     maxkeypage;     /* maximum keys per page */
-       int     minkeypage;     /* minimum keys per page */
-       u_int   psize;          /* page size */
+       u_int32_t flags;
+       u_int32_t cachesize;    /* bytes to cache */
+       u_int32_t maxkeypage;   /* maximum keys per page */
+       u_int32_t minkeypage;   /* minimum keys per page */
+       u_int32_t psize;        /* page size */
        int     (*compare)      /* comparison function */
            __P((const DBT *, const DBT *));
        size_t  (*prefix)       /* prefix function */
@@ -144,10 +144,10 @@ typedef struct {
 
 /* Structure used to pass parameters to the hashing routines. */
 typedef struct {
-       u_int   bsize;          /* bucket size */
-       u_int   ffactor;        /* fill factor */
-       u_int   nelem;          /* number of elements */
-       u_int   cachesize;      /* bytes to cache */
+       u_int32_t bsize;        /* bucket size */
+       u_int32_t ffactor;      /* fill factor */
+       u_int32_t nelem;        /* number of elements */
+       u_int32_t cachesize;    /* bytes to cache */
        u_int32_t               /* hash function */
                (*hash) __P((const void *, size_t));
        int     lorder;         /* byte order */
@@ -158,9 +158,9 @@ typedef struct {
 #define        R_FIXEDLEN      0x01    /* fixed-length records */
 #define        R_NOKEY         0x02    /* key not required */
 #define        R_SNAPSHOT      0x04    /* snapshot the input */
-       u_long  flags;
-       u_int   cachesize;      /* bytes to cache */
-       u_int   psize;          /* page size */
+       u_int32_t flags;
+       u_int32_t cachesize;    /* bytes to cache */
+       u_int32_t psize;        /* page size */
        int     lorder;         /* byte order */
        size_t  reclen;         /* record length (fixed-length records) */
        u_char  bval;           /* delimiting byte (variable-length records */
index 304e3fd..0c18924 100644 (file)
@@ -1,10 +1,10 @@
 /*-
  * See the file LICENSE for redistribution information.
  *
- * Copyright (c) 1996, 1997
+ * Copyright (c) 1996, 1997, 1998
  *     Sleepycat Software.  All rights reserved.
  *
- *     @(#)db_am.h     10.8 (Sleepycat) 1/8/98
+ *     @(#)db_am.h     10.9 (Sleepycat) 4/10/98
  */
 #ifndef _DB_AM_H
 #define _DB_AM_H
index 4c7b4da..1b07c74 100644 (file)
@@ -114,6 +114,9 @@ typedef struct _db_noop_args {
        u_int32_t type;
        DB_TXN *txnid;
        DB_LSN prev_lsn;
+       u_int32_t       fileid;
+       db_pgno_t       pgno;
+       DB_LSN  prevlsn;
 } __db_noop_args;
 
 #endif
index 83523c5..fc04d5d 100644 (file)
@@ -1,10 +1,10 @@
 /*-
  * See the file LICENSE for redistribution information.
  *
- * Copyright (c) 1997
+ * Copyright (c) 1997, 1998
  *     Sleepycat Software.  All rights reserved.
  *
- *     @(#)db_cxx.h    10.13 (Sleepycat) 11/25/97
+ *     @(#)db_cxx.h    10.17 (Sleepycat) 5/2/98
  */
 
 #ifndef _DB_CXX_H_
@@ -178,11 +178,11 @@ class _exported DbLock
     friend DbLockTab;
 
 public:
-    DbLock(unsigned int);
+    DbLock(u_int);
     DbLock();
 
-    unsigned int get_lock_id();
-    void set_lock_id(unsigned int);
+    u_int get_lock_id();
+    void set_lock_id(u_int);
 
     int put(DbLockTab *locktab);
 
@@ -202,16 +202,16 @@ class _exported DbLockTab
 friend DbEnv;
 public:
     int close();
-    int detect(int flags, int atype);
-    int get(u_int32_t locker, int flags, const Dbt *obj,
+    int detect(u_int32_t flags, int atype);
+    int get(u_int32_t locker, u_int32_t flags, const Dbt *obj,
             db_lockmode_t lock_mode, DbLock *lock);
     int id(u_int32_t *idp);
-    int vec(u_int32_t locker, int flags, DB_LOCKREQ list[],
+    int vec(u_int32_t locker, u_int32_t flags, DB_LOCKREQ list[],
            int nlist, DB_LOCKREQ **elistp);
 
     // Create or remove new locktab files
     //
-    static int open(const char *dir, int flags, int mode,
+    static int open(const char *dir, u_int32_t flags, int mode,
                     DbEnv* dbenv, DbLockTab **regionp);
     static int unlink(const char *dir, int force, DbEnv* dbenv);
 
@@ -252,13 +252,13 @@ class _exported DbLog
 {
 friend DbEnv;
 public:
-    int archive(char **list[], int flags, void *(*db_malloc)(size_t));
+    int archive(char **list[], u_int32_t flags, void *(*db_malloc)(size_t));
     int close();
     static int compare(const DbLsn *lsn0, const DbLsn *lsn1);
     int file(DbLsn *lsn, char *namep, int len);
     int flush(const DbLsn *lsn);
-    int get(DbLsn *lsn, Dbt *data, int flags);
-    int put(DbLsn *lsn, const Dbt *data, int flags);
+    int get(DbLsn *lsn, Dbt *data, u_int32_t flags);
+    int put(DbLsn *lsn, const Dbt *data, u_int32_t flags);
 
     // Normally these would be called register and unregister to
     // parallel the C interface, but "register" is a reserved word.
@@ -268,7 +268,7 @@ public:
 
     // Create or remove new log files
     //
-    static int open(const char *dir, int flags, int mode,
+    static int open(const char *dir, u_int32_t flags, int mode,
                     DbEnv* dbenv, DbLog **regionp);
     static int unlink(const char *dir, int force, DbEnv* dbenv);
 
@@ -300,17 +300,17 @@ private:
 
 class _exported DbMpoolFile
 {
+friend DbEnv;
 public:
     int close();
-    int get(db_pgno_t *pgnoaddr, int flags, void *pagep);
-    int put(void *pgaddr, int flags);
-    int set(void *pgaddr, int flags);
+    int get(db_pgno_t *pgnoaddr, u_int32_t flags, void *pagep);
+    int put(void *pgaddr, u_int32_t flags);
+    int set(void *pgaddr, u_int32_t flags);
     int sync();
 
     static int open(DbMpool *mp, const char *file,
-                    int ftype, int flags, int mode,
-                    size_t pagesize, int lsn_offset,
-                    Dbt *pgcookie, u_int8_t *uid, DbMpoolFile **mpf);
+                    u_int32_t flags, int mode, size_t pagesize,
+                    DB_MPOOL_FINFO *finfop, DbMpoolFile **mpf);
 
 private:
     // We can add data to this class if needed
@@ -356,7 +356,7 @@ public:
 
     // Create or remove new mpool files
     //
-    static int open(const char *dir, int flags, int mode,
+    static int open(const char *dir, u_int32_t flags, int mode,
                     DbEnv* dbenv, DbMpool **regionp);
     static int unlink(const char *dir, int force, DbEnv* dbenv);
 
@@ -391,13 +391,13 @@ class _exported DbTxnMgr
 friend DbEnv;
 public:
     int begin(DbTxn *pid, DbTxn **tid);
-    int checkpoint(int kbyte, int min) const;
+    int checkpoint(u_int32_t kbyte, u_int32_t min) const;
     int close();
     int stat(DB_TXN_STAT **statp, void *(*db_malloc)(size_t));
 
     // Create or remove new txnmgr files
     //
-    static int open(const char *dir, int flags, int mode,
+    static int open(const char *dir, u_int32_t flags, int mode,
                     DbEnv* dbenv, DbTxnMgr **regionp);
     static int unlink(const char *dir, int force, DbEnv* dbenv);
 
@@ -510,12 +510,12 @@ public:
     // Hash access method.
 
     // Fill factor.
-    unsigned int get_h_ffactor() const;
-    void set_h_ffactor(unsigned int);
+    u_int32_t get_h_ffactor() const;
+    void set_h_ffactor(u_int32_t);
 
     // Number of elements.
-    unsigned int get_h_nelem() const;
-    void set_h_nelem(unsigned int);
+    u_int32_t get_h_nelem() const;
+    void set_h_nelem(u_int32_t);
 
     // Hash function.
     typedef u_int32_t (*h_hash_fcn)(const void *, u_int32_t);
@@ -584,7 +584,7 @@ public:
     // application with these arguments.  Do not use it if you
     // need to set other parameters via the access methods.
     //
-    DbEnv(const char *homeDir, char *const *db_config, int flags);
+    DbEnv(const char *homeDir, char *const *db_config, u_int32_t flags);
 
     // Use this constructor if you wish to *delay* the initialization
     // of the db library.  This is useful if you need to set
@@ -596,7 +596,7 @@ public:
     // Used in conjunction with the default constructor to
     // complete the initialization of the db library.
     //
-    int appinit(const char *homeDir, char *const *db_config, int flags);
+    int appinit(const char *homeDir, char *const *db_config, u_int32_t flags);
 
     // Called automatically when DbEnv is destroyed, or can be
     // called at any time to shut down Db.
@@ -673,8 +673,8 @@ public:
     void set_lk_modes(int);
 
     // Maximum number of locks.
-    unsigned int get_lk_max() const;
-    void set_lk_max(unsigned int);
+    u_int32_t get_lk_max() const;
+    void set_lk_max(u_int32_t);
 
     // Deadlock detect on every conflict.
     u_int32_t get_lk_detect() const;
@@ -714,8 +714,8 @@ public:
     DbTxnMgr *get_tx_info() const;
 
     // Maximum number of transactions.
-    unsigned int get_tx_max() const;
-    void set_tx_max(unsigned int);
+    u_int32_t get_tx_max() const;
+    void set_tx_max(u_int32_t);
 
     // Dispatch function for recovery.
     typedef int (*tx_recover_fcn)(DB_LOG *, DBT *, DB_LSN *, int, void *);
@@ -781,18 +781,18 @@ class _exported Db
     friend DbEnv;
 
 public:
-    int close(int flags);
+    int close(u_int32_t flags);
     int cursor(DbTxn *txnid, Dbc **cursorp);
-    int del(DbTxn *txnid, Dbt *key, int flags);
+    int del(DbTxn *txnid, Dbt *key, u_int32_t 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);
-    int stat(void *sp, void *(*db_malloc)(size_t), int flags);
-    int sync(int flags);
+    int get(DbTxn *txnid, Dbt *key, Dbt *data, u_int32_t flags);
+    int put(DbTxn *txnid, Dbt *key, Dbt *data, u_int32_t flags);
+    int stat(void *sp, void *(*db_malloc)(size_t), u_int32_t flags);
+    int sync(u_int32_t flags);
 
     DBTYPE get_type() const;
 
-    static int open(const char *fname, DBTYPE type, int flags,
+    static int open(const char *fname, DBTYPE type, u_int32_t flags,
                     int mode, DbEnv *dbenv, DbInfo *info, Db **dbpp);
 
 private:
@@ -867,9 +867,9 @@ class _exported Dbc : protected DBC
 
 public:
     int close();
-    int del(int flags);
-    int get(Dbt* key, Dbt *data, int flags);
-    int put(Dbt* key, Dbt *data, int flags);
+    int del(u_int32_t flags);
+    int get(Dbt* key, Dbt *data, u_int32_t flags);
+    int put(Dbt* key, Dbt *data, u_int32_t flags);
 
 private:
     // No data is permitted in this class (see comment at top)
index b93ec39..8f5e217 100644 (file)
@@ -1,7 +1,7 @@
 /*-
  * See the file LICENSE for redistribution information.
  *
- * Copyright (c) 1996, 1997
+ * Copyright (c) 1996, 1997, 1998
  *     Sleepycat Software.  All rights reserved.
  */
 /*
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- *     @(#)db_dispatch.h       10.1 (Sleepycat) 4/12/97
+ *     @(#)db_dispatch.h       10.4 (Sleepycat) 5/3/98
  */
 
 #ifndef _DB_DISPATCH_H
 #define _DB_DISPATCH_H
 
+struct __db_txnhead;   typedef struct __db_txnhead DB_TXNHEAD;
+struct __db_txnlist;   typedef struct __db_txnlist DB_TXNLIST;
+
 /*
  * Declarations and typedefs for the list of transaction IDs used during
  * recovery.
  */
-
-typedef struct __db_txnhead {
-       LIST_HEAD(__db_headlink, _db_txnlist) head;
+struct __db_txnhead {
+       LIST_HEAD(__db_headlink, __db_txnlist) head;
        u_int32_t maxid;
-} __db_txnhead;
+       int32_t generation;
+};
 
-typedef struct _db_txnlist {
-       LIST_ENTRY(_db_txnlist) links;
-       u_int32_t       txnid;
-} __db_txnlist;
+struct __db_txnlist {
+       LIST_ENTRY(__db_txnlist) links;
+       u_int32_t txnid;
+       int32_t generation;
+};
 
 #define        DB_log_BEGIN              0
 #define        DB_txn_BEGIN              5
index 122d8f1..8a03db9 100644 (file)
@@ -53,7 +53,8 @@ int __db_debug_print
    __P((DB_LOG *, DBT *, DB_LSN *, int, void *));
 int __db_debug_read __P((void *, __db_debug_args **));
 int __db_noop_log
-    __P((DB_LOG *, DB_TXN *, DB_LSN *, u_int32_t));
+    __P((DB_LOG *, DB_TXN *, DB_LSN *, u_int32_t,
+    u_int32_t, db_pgno_t, DB_LSN *));
 int __db_noop_print
    __P((DB_LOG *, DBT *, DB_LSN *, int, void *));
 int __db_noop_read __P((void *, __db_noop_args **));
@@ -67,8 +68,9 @@ int __db_add_recovery __P((DB_ENV *,
 int __db_txnlist_init __P((void *));
 int __db_txnlist_add __P((void *, u_int32_t));
 int __db_txnlist_find __P((void *, u_int32_t));
-void __db_txnlist_print __P((void *));
 void __db_txnlist_end __P((void *));
+void __db_txnlist_gen __P((void *, int));
+void __db_txnlist_print __P((void *));
 int __db_dput __P((DB *,
    DBT *, PAGE **, db_indx_t *, int (*)(DB *, u_int32_t, PAGE **)));
 int __db_drem __P((DB *,
@@ -83,7 +85,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_ovref __P((DB *, db_pgno_t, int));
+int __db_ovref __P((DB *, db_pgno_t, int32_t));
 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));
@@ -97,7 +99,8 @@ int __db_prnpage __P((DB_MPOOLFILE *, db_pgno_t));
 int __db_prpage __P((PAGE *, int));
 int __db_isbad __P((PAGE *, int));
 void __db_pr __P((u_int8_t *, u_int32_t));
-void __db_prflags __P((u_int32_t, const FN *));
+int __db_prdbt __P((DBT *, int, FILE *));
+void __db_prflags __P((u_int32_t, const FN *, FILE *));
 int __db_addrem_recover
    __P((DB_LOG *, DBT *, DB_LSN *, int, void *));
 int __db_split_recover __P((DB_LOG *, DBT *, DB_LSN *, int, void *));
@@ -108,8 +111,7 @@ int __db_relink_recover
 int __db_addpage_recover
    __P((DB_LOG *, DBT *, DB_LSN *, int, void *));
 int __db_debug_recover __P((DB_LOG *, DBT *, DB_LSN *, int, void *));
-int __db_noop_recover
-  __P((DB_LOG *, DBT *, DB_LSN *, int, void *));
+int __db_noop_recover __P((DB_LOG *, DBT *, DB_LSN *, int, void *));
 int __db_ret __P((DB *,
    PAGE *, u_int32_t, DBT *, void **, u_int32_t *));
 int __db_retcopy __P((DBT *,
index 48790d6..d67e2c4 100644 (file)
@@ -1,10 +1,10 @@
 /*-
  * See the file LICENSE for redistribution information.
  *
- * Copyright (c) 1996, 1997
+ * Copyright (c) 1996, 1997, 1998
  *     Sleepycat Software.  All rights reserved.
  *
- *     @(#)db_int.h.src        10.41 (Sleepycat) 1/8/98
+ *     @(#)db_int.h.src        10.62 (Sleepycat) 5/23/98
  */
 
 #ifndef _DB_INTERNAL_H_
@@ -12,8 +12,6 @@
 
 #include "db.h"                                /* Standard DB include file. */
 #include "queue.h"
-#include "os_func.h"
-#include "os_ext.h"
 
 /*******************************************************
  * General purpose constants and macros.
@@ -77,8 +75,8 @@
 #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
+/* Free and free-string macros that overwrite memory. */
+#ifdef DIAGNOSTIC
 #undef FREE
 #define        FREE(p, len) {                                                  \
        memset(p, 0xff, len);                                           \
@@ -117,36 +115,41 @@ typedef struct __fn {
 #undef DB_LINE
 #define        DB_LINE "=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-="
 
+/* Global variables. */
+typedef struct __db_globals {
+       int db_mutexlocks;              /* DB_MUTEXLOCKS */
+       int db_region_anon;             /* DB_REGION_ANON, DB_REGION_NAME */
+       int db_region_init;             /* DB_REGION_INIT */
+       int db_tsl_spins;               /* DB_TSL_SPINS */
+       int db_pageyield;               /* DB_PAGEYIELD */
+} DB_GLOBALS;
+extern DB_GLOBALS      __db_global_values;
+#define        DB_GLOBAL(v)    __db_global_values.v
+
 /* Unused, or not-used-yet variable.  "Shut that bloody compiler up!" */
 #define        COMPQUIET(n, v) (n) = (v)
 
+/*
+ * Win16 needs specific syntax on callback functions.  Nobody else cares.
+ */
+#ifndef        DB_CALLBACK
+#define        DB_CALLBACK     /* Nothing. */
+#endif
+
 /*******************************************************
  * Files.
  *******************************************************/
-#ifndef MAXPATHLEN             /* Maximum path length. */
-#ifdef PATH_MAX
-#define        MAXPATHLEN      PATH_MAX
-#else
+ /*
+  * We use 1024 as the maximum path length.  It's too hard to figure out what
+  * the real path length is, as it was traditionally stored in <sys/param.h>,
+  * and that file isn't always available.
+  */
+#undef MAXPATHLEN
 #define        MAXPATHLEN      1024
-#endif
-#endif
 
 #define        PATH_DOT        "."     /* Current working directory. */
 #define        PATH_SEPARATOR  "/"     /* Path separator character. */
 
-#ifndef S_IRUSR                        /* UNIX specific file permissions. */
-#define        S_IRUSR 0000400         /* R for owner */
-#define        S_IWUSR 0000200         /* W for owner */
-#define        S_IRGRP 0000040         /* R for group */
-#define        S_IWGRP 0000020         /* W for group */
-#define        S_IROTH 0000004         /* R for other */
-#define        S_IWOTH 0000002         /* W for other */
-#endif
-
-#ifndef S_ISDIR                        /* UNIX specific: directory test. */
-#define        S_ISDIR(m)      ((m & 0170000) == 0040000)
-#endif
-
 /*******************************************************
  * Mutex support.
  *******************************************************/
@@ -176,12 +179,12 @@ typedef struct __fn {
 typedef struct _db_mutex_t {
 #ifdef HAVE_SPINLOCKS
        tsl_t     tsl_resource;         /* Resource test and set. */
-#ifdef DEBUG
-       u_long    pid;                  /* Lock holder: 0 or process pid. */
+#ifdef DIAGNOSTIC
+       u_int32_t pid;                  /* Lock holder: 0 or process pid. */
 #endif
 #else
        u_int32_t off;                  /* Backing file offset. */
-       u_long    pid;                  /* Lock holder: 0 or process pid. */
+       u_int32_t pid;                  /* Lock holder: 0 or process pid. */
 #endif
        u_int32_t spins;                /* Spins before block. */
        u_int32_t mutex_set_wait;       /* Granted after wait. */
@@ -195,11 +198,11 @@ 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) : 0)
+       if (F_ISSET(dbp, DB_AM_THREAD))                                 \
+           (void)__db_mutex_lock((db_mutex_t *)(dbp)->mutexp, -1);
 #define        DB_THREAD_UNLOCK(dbp)                                           \
-       (F_ISSET(dbp, DB_AM_THREAD) ?                                   \
-           __db_mutex_unlock((db_mutex_t *)(dbp)->mutexp, -1) : 0)
+       if (F_ISSET(dbp, DB_AM_THREAD))                                 \
+           (void)__db_mutex_unlock((db_mutex_t *)(dbp)->mutexp, -1);
 
 /* Btree/recno local statistics structure. */
 struct __db_bt_lstat;  typedef struct __db_bt_lstat DB_BTREE_LSTAT;
@@ -228,7 +231,7 @@ typedef enum {
 } APPNAME;
 
 /*******************************************************
- * Regions.
+ * Shared memory regions.
  *******************************************************/
 /*
  * The shared memory regions share an initial structure so that the general
@@ -240,16 +243,69 @@ typedef enum {
  */
 typedef struct _rlayout {
        db_mutex_t lock;                /* Region mutex. */
+#define        DB_REGIONMAGIC  0x120897
+       u_int32_t  valid;               /* Valid magic number. */
        u_int32_t  refcnt;              /* Region reference count. */
        size_t     size;                /* Region length. */
        int        majver;              /* Major version number. */
        int        minver;              /* Minor version number. */
        int        patch;               /* Patch version number. */
+#define        INVALID_SEGID   -1
+       int        segid;               /* shmget(2) ID, or Win16 segment ID. */
 
-#define        DB_R_DELETED    0x01            /* Region was deleted. */
+#define        REGION_ANONYMOUS        0x01    /* Region is/should be in anon mem. */
        u_int32_t  flags;
 } RLAYOUT;
 
+/*
+ * DB creates all regions on 4K boundaries out of sheer paranoia, so that
+ * we don't make the underlying VM unhappy.
+ */
+#define        DB_VMPAGESIZE   (4 * 1024)
+#define        DB_ROUNDOFF(i) {                                                \
+       (i) += DB_VMPAGESIZE - 1;                                       \
+       (i) -= (i) % DB_VMPAGESIZE;                                     \
+}
+
+/*
+ * The interface to region attach is nasty, there is a lot of complex stuff
+ * going on, which has to be retained between create/attach and detach.  The
+ * REGINFO structure keeps track of it.
+ */
+struct __db_reginfo;   typedef struct __db_reginfo REGINFO;
+struct __db_reginfo {
+                                       /* Arguments. */
+       DB_ENV     *dbenv;              /* Region naming info. */
+       APPNAME     appname;            /* Region naming info. */
+       char       *path;               /* Region naming info. */
+       const char *file;               /* Region naming info. */
+       int         mode;               /* Region mode, if a file. */
+       size_t      size;               /* Region size. */
+       u_int32_t   dbflags;            /* Region file open flags, if a file. */
+
+                                       /* Results. */
+       char       *name;               /* Region name. */
+       void       *addr;               /* Region address. */
+       int         fd;                 /* Fcntl(2) locking file descriptor.
+                                          NB: this is only valid if a regular
+                                          file is backing the shared region,
+                                          and mmap(2) is being used to map it
+                                          into our address space. */
+       int         segid;              /* shmget(2) ID, or Win16 segment ID. */
+
+                                       /* Shared flags. */
+/*                             0x0001  COMMON MASK with RLAYOUT structure. */
+#define        REGION_CANGROW          0x0002  /* Can grow. */
+#define        REGION_CREATED          0x0004  /* Created. */
+#define        REGION_HOLDINGSYS       0x0008  /* Holding system resources. */
+#define        REGION_LASTDETACH       0x0010  /* Delete on last detach. */
+#define        REGION_MALLOC           0x0020  /* Created in malloc'd memory. */
+#define        REGION_PRIVATE          0x0040  /* Private to thread/process. */
+#define        REGION_REMOVED          0x0080  /* Already deleted. */
+#define        REGION_SIZEDEF          0x0100  /* Use default region size if exists. */
+       u_int32_t   flags;
+};
+
 /*******************************************************
  * Mpool.
  *******************************************************/
@@ -281,7 +337,7 @@ typedef struct __dbpginfo {
 #define        DB_LOGGING(dbp)                                                 \
        (F_ISSET(dbp, DB_AM_LOGGING) && !F_ISSET(dbp, DB_AM_RECOVER))
 
-#ifdef DEBUG
+#ifdef DIAGNOSTIC
 /*
  * Debugging macro to log operations.
  *     If DEBUG_WOP is defined, log operations that modify the database.
@@ -318,7 +374,7 @@ typedef struct __dbpginfo {
 #else
 #define        DEBUG_LREAD(D, T, O, K, A, F)
 #define        DEBUG_LWRITE(D, T, O, K, A, F)
-#endif /* DEBUG */
+#endif /* DIAGNOSTIC */
 
 /*******************************************************
  * Transactions and recovery.
@@ -339,4 +395,8 @@ struct __db_txn {
        size_t          off;            /* Detail structure within region. */
        TAILQ_ENTRY(__db_txn) links;
 };
+
+#include "os_func.h"
+#include "os_ext.h"
+
 #endif /* !_DB_INTERNAL_H_ */
index 30f6072..e1846cb 100644 (file)
@@ -1,10 +1,10 @@
 /*-
  * See the file LICENSE for redistribution information.
  *
- * Copyright (c) 1996, 1997
+ * Copyright (c) 1996, 1997, 1998
  *     Sleepycat Software.  All rights reserved.
  *
- *     @(#)db_page.h   10.13 (Sleepycat) 9/24/97
+ *     @(#)db_page.h   10.15 (Sleepycat) 5/1/98
  */
 
 #ifndef _DB_PAGE_H_
 #define        PGNO_INVALID    0       /* Metadata page number, therefore illegal. */
 #define        PGNO_ROOT       1       /* Root is page #1. */
 
+/*
+ * When we create pages in mpool, we ask mpool to clear some number of bytes
+ * in the header.  This number must be at least as big as the regular page
+ * headers and cover enough of the btree and hash meta-data pages to obliterate
+ * the magic and version numbers.
+ */
+#define        DB_PAGE_CLEAR_LEN       32
+
 /************************************************************************
  BTREE METADATA PAGE LAYOUT
  ************************************************************************/
index b94e0f1..35ade39 100644 (file)
@@ -1,10 +1,10 @@
 /*-
  * See the file LICENSE for redistribution information.
  *
- * Copyright (c) 1996, 1997
+ * Copyright (c) 1996, 1997, 1998
  *     Sleepycat Software.  All rights reserved.
  *
- *     @(#)db_shash.h  10.2 (Sleepycat) 9/16/97
+ *     @(#)db_shash.h  10.3 (Sleepycat) 4/10/98
  */
 
 /* Hash Headers */
index 278282f..9f94ed7 100644 (file)
@@ -1,7 +1,7 @@
 /*-
  * See the file LICENSE for redistribution information.
  *
- * Copyright (c) 1996, 1997
+ * Copyright (c) 1996, 1997, 1998
  *     Sleepycat Software.  All rights reserved.
  */
 /*
@@ -36,7 +36,7 @@
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- *     @(#)db_swap.h   10.3 (Sleepycat) 6/10/97
+ *     @(#)db_swap.h   10.5 (Sleepycat) 4/10/98
  */
 
 #ifndef _DB_SWAP_H_
@@ -74,7 +74,7 @@
 /*
  * Little endian <==> big endian 16-bit swap macros.
  *     M_16_SWAP       swap a memory location
- *     P_16_COPY       copy potentially unaligned  from one location to another
+ *     P_16_COPY       copy potentially unaligned 2 byte quantities
  *     P_16_SWAP       swap a referenced memory location
  */
 #define        M_16_SWAP(a) {                                                  \
index ae6d384..e55c210 100644 (file)
@@ -1,7 +1,7 @@
 /*-
  * See the file LICENSE for redistribution information.
  *
- * Copyright (c) 1996, 1997
+ * Copyright (c) 1996, 1997, 1998
  *     Sleepycat Software.  All rights reserved.
  */
 /*
@@ -43,7 +43,7 @@
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- *     @(#)hash.h      10.7 (Sleepycat) 11/1/97
+ *     @(#)hash.h      10.8 (Sleepycat) 4/10/98
  */
 
 /* Cursor structure definitions. */
index 9b97d35..7086adc 100644 (file)
@@ -2,7 +2,7 @@
 #ifndef _hash_ext_h_
 #define _hash_ext_h_
 int __ham_open __P((DB *, DB_INFO *));
-int  __ham_close __P((DB *));
+int __ham_close __P((DB *));
 int __ham_c_iclose __P((DB *, DBC *));
 int __ham_expand_table __P((HTAB *));
 u_int32_t __ham_call_hash __P((HTAB *, u_int8_t *, int32_t));
@@ -75,7 +75,7 @@ int __ham_mswap __P((void *));
 #ifdef DEBUG
 void __ham_dump_bucket __P((HTAB *, u_int32_t));
 #endif
-int __ham_add_dup __P((HTAB *, HASH_CURSOR *, DBT *, int));
+int __ham_add_dup __P((HTAB *, HASH_CURSOR *, DBT *, u_int32_t));
 void __ham_move_offpage __P((HTAB *, PAGE *, u_int32_t, db_pgno_t));
 u_int32_t __ham_func2 __P((const void *, u_int32_t));
 u_int32_t __ham_func3 __P((const void *, u_int32_t));
@@ -90,14 +90,16 @@ int __ham_item_first __P((HTAB *, HASH_CURSOR *, db_lockmode_t));
 int __ham_item_prev __P((HTAB *, HASH_CURSOR *, db_lockmode_t));
 int __ham_item_next __P((HTAB *, HASH_CURSOR *, db_lockmode_t));
 void __ham_putitem __P((PAGE *p, const DBT *, int));
+void __ham_reputpair
+   __P((PAGE *p, u_int32_t, u_int32_t, const DBT *, const DBT *));
 int __ham_del_pair __P((HTAB *, HASH_CURSOR *, int));
 int __ham_replpair __P((HTAB *, HASH_CURSOR *, DBT *, u_int32_t));
 void __ham_onpage_replace __P((PAGE *, size_t, u_int32_t, int32_t,
     int32_t,  DBT *));
 int __ham_split_page __P((HTAB *, u_int32_t, u_int32_t));
-int __ham_add_el __P((HTAB *, HASH_CURSOR *, const DBT *, const DBT *,
-    int));
-void __ham_copy_item __P((HTAB *, PAGE *, int, PAGE *));
+int __ham_add_el
+   __P((HTAB *, HASH_CURSOR *, const DBT *, const DBT *, int));
+void __ham_copy_item __P((HTAB *, PAGE *, u_int32_t, PAGE *));
 int __ham_add_ovflpage __P((HTAB *, PAGE *, int, PAGE **));
 int __ham_new_page __P((HTAB *, u_int32_t, u_int32_t, PAGE **));
 int __ham_del_page __P((DB *, PAGE *));
@@ -106,12 +108,12 @@ int __ham_dirty_page __P((HTAB *, PAGE *));
 int __ham_get_page __P((DB *, db_pgno_t, PAGE **));
 int __ham_overflow_page __P((DB *, u_int32_t, PAGE **));
 #ifdef DEBUG
-int __bucket_to_page __P((HTAB *, int));
+db_pgno_t __bucket_to_page __P((HTAB *, db_pgno_t));
 #endif
 void __ham_init_ovflpages __P((HTAB *));
 int __ham_get_cpage __P((HTAB *, HASH_CURSOR *, db_lockmode_t));
-int __ham_next_cpage __P((HTAB *, HASH_CURSOR *, db_pgno_t,
-    int, int));
+int __ham_next_cpage
+   __P((HTAB *, HASH_CURSOR *, db_pgno_t, int, u_int32_t));
 void __ham_dpair __P((DB *, PAGE *, u_int32_t));
 int __ham_insdel_recover
     __P((DB_LOG *, DBT *, DB_LSN *, int, void *));
index 5031b65..47a38b8 100644 (file)
@@ -1,16 +1,19 @@
 /*-
  * See the file LICENSE for redistribution information.
  *
- * Copyright (c) 1996, 1997
+ * Copyright (c) 1996, 1997, 1998
  *     Sleepycat Software.  All rights reserved.
  *
- *     @(#)lock.h      10.10 (Sleepycat) 11/13/97
+ *     @(#)lock.h      10.15 (Sleepycat) 5/10/98
  */
 
 typedef struct __db_lockobj    DB_LOCKOBJ;
 
 #define DB_DEFAULT_LOCK_FILE   "__db_lock.share"
-#define DB_LOCK_DEFAULT_N      5000
+
+#ifndef DB_LOCK_DEFAULT_N
+#define DB_LOCK_DEFAULT_N      5000    /* Default # of locks in region. */
+#endif
 
 /*
  * The locker id space is divided between the transaction manager and the lock
@@ -54,9 +57,9 @@ struct __db_lockregion {
 
 /* Macros to lock/unlock the region. */
 #define        LOCK_LOCKREGION(lt)                                             \
-       (void)__db_mutex_lock(&(lt)->region->hdr.lock, (lt)->fd)
+       (void)__db_mutex_lock(&(lt)->region->hdr.lock, (lt)->reginfo.fd)
 #define        UNLOCK_LOCKREGION(lt)                                           \
-       (void)__db_mutex_unlock(&(lt)->region->hdr.lock, (lt)->fd)
+       (void)__db_mutex_unlock(&(lt)->region->hdr.lock, (lt)->reginfo.fd)
 
 /*
  * Since we will be keeping DBTs in shared memory, we need the equivalent
@@ -69,9 +72,6 @@ typedef struct __sh_dbt {
 
 #define SH_DBT_PTR(p)  ((void *)(((u_int8_t *)(p)) + (p)->off))
 
-/*
- * The lock table is the per-process cookie returned from a lock_open call.
- */
 struct __db_lockobj {
        SH_DBT  lockobj;                /* Identifies object locked. */
        SH_TAILQ_ENTRY links;           /* Links for free list. */
@@ -98,12 +98,14 @@ struct __db_lockobj {
 #define        holders dlinks._holders
 #define        heldby  dlinks._heldby
 
+/*
+ * The lock table is the per-process cookie returned from a lock_open call.
+ */
 struct __db_locktab {
        DB_ENV          *dbenv;         /* Environment. */
-       int              fd;            /* mapped file descriptor */
-       DB_LOCKREGION   *region;        /* address of shared memory region */
+       REGINFO          reginfo;       /* Region information. */
+       DB_LOCKREGION   *region;        /* Address of shared memory region. */
        DB_HASHTAB      *hashtab;       /* Beginning of hash table. */
-       size_t          reg_size;       /* last known size of lock region */
        void            *mem;           /* Beginning of string space. */
        u_int8_t        *conflicts;     /* Pointer to conflict matrix. */
 };
@@ -113,21 +115,6 @@ struct __db_locktab {
        T->conflicts[HELD * T->region->nmodes + WANTED]
 
 /*
- * Status of a lock.
- */
-typedef enum {
-       DB_LSTAT_ABORTED,               /* Lock belongs to an aborted txn. */
-       DB_LSTAT_ERR,                   /* Lock is bad. */
-       DB_LSTAT_FREE,                  /* Lock is unallocated. */
-       DB_LSTAT_HELD,                  /* Lock is currently held. */
-       DB_LSTAT_NOGRANT,               /* Lock was not granted. */
-       DB_LSTAT_PENDING,               /* Lock was waiting and has been
-                                        * promoted; waiting for the owner
-                                        * to run and upgrade it to held. */
-       DB_LSTAT_WAITING                /* Lock is on the wait queue. */
-} db_status_t;
-
-/*
  * Resources in the lock region.  Used to indicate which resource
  * is running low when we need to grow the region.
  */
@@ -187,17 +174,4 @@ struct __db_lock {
        ALIGN((N) * sizeof(DB_LOCKOBJ), sizeof(size_t)) +               \
        ALIGN(STRING_SIZE(N), sizeof(size_t)))
 
-#ifdef DEBUG
-#define        LOCK_DEBUG_LOCKERS      0x0001
-#define        LOCK_DEBUG_LOCK         0x0002
-#define        LOCK_DEBUG_OBJ          0x0004
-#define        LOCK_DEBUG_CONF         0x0008
-#define        LOCK_DEBUG_MEM          0x0010
-#define        LOCK_DEBUG_BUCKET       0x0020
-#define LOCK_DEBUG_OBJECTS     0x0040
-#define        LOCK_DEBUG_ALL          0xFFFF
-
-#define        LOCK_DEBUG_NOMUTEX      0x0100
-#endif
-
 #include "lock_ext.h"
index d983b29..1e0522c 100644 (file)
@@ -1,14 +1,17 @@
 /* DO NOT EDIT: automatically built by dist/distrib. */
 #ifndef _lock_ext_h_
 #define _lock_ext_h_
-void __lock_dump_region __P((DB_LOCKTAB *, u_int));
 int __lock_is_locked
    __P((DB_LOCKTAB *, u_int32_t, DBT *, db_lockmode_t));
+void __lock_printlock __P((DB_LOCKTAB *, struct __db_lock *, int));
 int __lock_getobj  __P((DB_LOCKTAB *,
     u_int32_t, const DBT *, u_int32_t type, DB_LOCKOBJ **));
+int __lock_validate_region __P((DB_LOCKTAB *));
+int __lock_grow_region __P((DB_LOCKTAB *, int, size_t));
+void __lock_dump_region __P((DB_LOCKTAB *, char *, FILE *));
 int __lock_cmp __P((const DBT *, DB_LOCKOBJ *));
 int __lock_locker_cmp __P((u_int32_t, DB_LOCKOBJ *));
-int __lock_ohash __P((const DBT *));
-u_int32_t __lock_locker_hash __P((u_int32_t));
+u_int32_t __lock_ohash __P((const DBT *));
 u_int32_t __lock_lhash __P((DB_LOCKOBJ *));
+u_int32_t __lock_locker_hash __P((u_int32_t));
 #endif /* _lock_ext_h_ */
index 4e27b03..7d5161c 100644 (file)
@@ -1,10 +1,10 @@
 /*-
  * See the file LICENSE for redistribution information.
  *
- * Copyright (c) 1996, 1997
+ * Copyright (c) 1996, 1997, 1998
  *     Sleepycat Software.  All rights reserved.
  *
- *     @(#)log.h       10.19 (Sleepycat) 1/17/98
+ *     @(#)log.h       10.25 (Sleepycat) 4/10/98
  */
 
 #ifndef _LOG_H_
@@ -15,9 +15,10 @@ struct __hdr;                typedef struct __hdr HDR;
 struct __log;          typedef struct __log LOG;
 struct __log_persist;  typedef struct __log_persist LOGP;
 
+#ifndef MAXLFNAME
 #define        MAXLFNAME       99999           /* Maximum log file name. */
 #define        LFNAME          "log.%05d"      /* Log file name template. */
-
+#endif
                                        /* Default log name. */
 #define DB_DEFAULT_LOG_FILE    "__db_log.share"
 
@@ -31,17 +32,19 @@ struct __log_persist;       typedef struct __log_persist LOGP;
        if (F_ISSET(dblp, DB_AM_THREAD))                                \
                (void)__db_mutex_unlock((dblp)->mutexp, -1);
 #define        LOCK_LOGREGION(dblp)                                            \
-       (void)__db_mutex_lock(&((RLAYOUT *)(dblp)->lp)->lock, (dblp)->fd)
+       (void)__db_mutex_lock(&((RLAYOUT *)(dblp)->lp)->lock,           \
+           (dblp)->reginfo.fd)
 #define        UNLOCK_LOGREGION(dblp)                                          \
-       (void)__db_mutex_unlock(&((RLAYOUT *)(dblp)->lp)->lock, (dblp)->fd)
+       (void)__db_mutex_unlock(&((RLAYOUT *)(dblp)->lp)->lock,         \
+           (dblp)->reginfo.fd)
 
 /*
  * The per-process table that maps log file-id's to DB structures.
  */
 typedef        struct __db_entry {
-       DB      *dbp;                   /* Associated DB structure. */
-       int     refcount;               /* Reference counted. */
-       int     deleted;                /* File was not found during open. */
+       DB       *dbp;                  /* Associated DB structure. */
+       u_int32_t refcount;             /* Reference counted. */
+       int       deleted;              /* File was not found during open. */
 } DB_ENTRY;
 
 /*
@@ -75,10 +78,9 @@ struct __db_log {
        LOG      *lp;                   /* Address of the shared LOG. */
 
        DB_ENV   *dbenv;                /* Reference to error information. */
+       REGINFO   reginfo;              /* Region information. */
 
-       void     *maddr;                /* Address of mmap'd region. */
        void     *addr;                 /* Address of shalloc() region. */
-       int       fd;                   /* Region file descriptor. */
 
        char     *dir;                  /* Directory argument. */
 
@@ -131,7 +133,7 @@ struct __log {
 
        u_int32_t w_off;                /* Current write offset in the file. */
 
-       DB_LSN    c_lsn;                /* LSN of the last checkpoint. */
+       DB_LSN    chkpt_lsn;            /* LSN of the last checkpoint. */
        time_t    chkpt;                /* Time of the last checkpoint. */
 
        DB_LOG_STAT stat;               /* Log statistics. */
@@ -159,9 +161,8 @@ struct __fname {
        u_int32_t id;                   /* Logging file id. */
        DBTYPE    s_type;               /* Saved DB type. */
 
-       u_int32_t fileid_off;           /* Unique file id offset. */
-
        size_t    name_off;             /* Name offset. */
+       u_int8_t  ufid[DB_FILE_ID_LEN]; /* Unique file id. */
 };
 
 /* File open/close register log record opcodes. */
index 8640b13..bf3bcb0 100644 (file)
@@ -13,8 +13,8 @@ int __log_register_read __P((void *, __log_register_args **));
 int __log_init_print __P((DB_ENV *));
 int __log_init_recover __P((DB_ENV *));
 int __log_findckp __P((DB_LOG *, DB_LSN *));
-int __log_get __P((DB_LOG *, DB_LSN *, DBT *, int, int));
-int __log_put __P((DB_LOG *, DB_LSN *, const DBT *, int));
+int __log_get __P((DB_LOG *, DB_LSN *, DBT *, u_int32_t, int));
+int __log_put __P((DB_LOG *, DB_LSN *, const DBT *, u_int32_t));
 int __log_name __P((DB_LOG *, int, char **));
 int __log_register_recover
     __P((DB_LOG *, DBT *, DB_LSN *, int, void *));
index 4efbf9b..8635efa 100644 (file)
@@ -1,10 +1,10 @@
 /*-
  * See the file LICENSE for redistribution information.
  *
- * Copyright (c) 1996, 1997
+ * Copyright (c) 1996, 1997, 1998
  *     Sleepycat Software.  All rights reserved.
  *
- *     @(#)mp.h        10.25 (Sleepycat) 1/8/98
+ *     @(#)mp.h        10.33 (Sleepycat) 5/4/98
  */
 
 struct __bh;           typedef struct __bh BH;
@@ -16,10 +16,12 @@ struct __mpoolfile; typedef struct __mpoolfile MPOOLFILE;
 #define        DB_DEFAULT_MPOOL_FILE   "__db_mpool.share"
 
 /*
- *  We default to 128K (16 8K pages) if the user doesn't specify, and
+ * We default to 128K (16 8K pages) if the user doesn't specify, and
  * require a minimum of 20K.
  */
+#ifndef        DB_CACHESIZE_DEF
 #define        DB_CACHESIZE_DEF        (128 * 1024)
+#endif
 #define        DB_CACHESIZE_MIN        ( 20 * 1024)
 
 #define        INVALID         0               /* Invalid shared memory offset. */
@@ -79,30 +81,30 @@ struct __mpoolfile; typedef struct __mpoolfile MPOOLFILE;
 #define        LOCKINIT(dbmp, mutexp)                                          \
        if (F_ISSET(dbmp, MP_LOCKHANDLE | MP_LOCKREGION))               \
                (void)__db_mutex_init(mutexp,                           \
-                   MUTEX_LOCK_OFFSET((dbmp)->maddr, mutexp))
+                   MUTEX_LOCK_OFFSET((dbmp)->reginfo.addr, mutexp))
 
 #define        LOCKHANDLE(dbmp, mutexp)                                        \
        if (F_ISSET(dbmp, MP_LOCKHANDLE))                               \
-               (void)__db_mutex_lock(mutexp, (dbmp)->fd)
+               (void)__db_mutex_lock(mutexp, (dbmp)->reginfo.fd)
 #define        UNLOCKHANDLE(dbmp, mutexp)                                      \
        if (F_ISSET(dbmp, MP_LOCKHANDLE))                               \
-               (void)__db_mutex_unlock(mutexp, (dbmp)->fd)
+               (void)__db_mutex_unlock(mutexp, (dbmp)->reginfo.fd)
 
 #define        LOCKREGION(dbmp)                                                \
        if (F_ISSET(dbmp, MP_LOCKREGION))                               \
                (void)__db_mutex_lock(&((RLAYOUT *)(dbmp)->mp)->lock,   \
-                   (dbmp)->fd)
+                   (dbmp)->reginfo.fd)
 #define        UNLOCKREGION(dbmp)                                              \
        if (F_ISSET(dbmp, MP_LOCKREGION))                               \
                (void)__db_mutex_unlock(&((RLAYOUT *)(dbmp)->mp)->lock, \
-               (dbmp)->fd)
+               (dbmp)->reginfo.fd)
 
 #define        LOCKBUFFER(dbmp, bhp)                                           \
        if (F_ISSET(dbmp, MP_LOCKREGION))                               \
-               (void)__db_mutex_lock(&(bhp)->mutex, (dbmp)->fd)
+               (void)__db_mutex_lock(&(bhp)->mutex, (dbmp)->reginfo.fd)
 #define        UNLOCKBUFFER(dbmp, bhp)                                         \
        if (F_ISSET(dbmp, MP_LOCKREGION))                               \
-               (void)__db_mutex_unlock(&(bhp)->mutex, (dbmp)->fd)
+               (void)__db_mutex_unlock(&(bhp)->mutex, (dbmp)->reginfo.fd)
 
 /*
  * DB_MPOOL --
@@ -120,20 +122,16 @@ struct __db_mpool {
 
 /* These fields are not protected. */
        DB_ENV     *dbenv;              /* Reference to error information. */
+       REGINFO     reginfo;            /* Region information. */
 
        MPOOL      *mp;                 /* Address of the shared MPOOL. */
 
-       void       *maddr;              /* Address of mmap'd region. */
        void       *addr;               /* Address of shalloc() region. */
 
        DB_HASHTAB *htab;               /* Hash table of bucket headers. */
 
-       int         fd;                 /* Underlying mmap'd fd. */
-
-#define        MP_ISPRIVATE    0x01            /* Private, so local memory. */
-#define        MP_LOCKHANDLE   0x02            /* Threaded, lock handles and region. */
-#define        MP_LOCKREGION   0x04            /* Concurrent access, lock region. */
-#define        MP_MALLOC       0x08            /* If region in allocated memory. */
+#define        MP_LOCKHANDLE   0x01            /* Threaded, lock handles and region. */
+#define        MP_LOCKREGION   0x02            /* Concurrent access, lock region. */
        u_int32_t  flags;
 };
 
@@ -146,8 +144,8 @@ struct __db_mpreg {
 
        int ftype;                      /* File type. */
                                        /* Pgin, pgout routines. */
-       int (*pgin) __P((db_pgno_t, void *, DBT *));
-       int (*pgout) __P((db_pgno_t, void *, DBT *));
+       int (DB_CALLBACK *pgin) __P((db_pgno_t, void *, DBT *));
+       int (DB_CALLBACK *pgout) __P((db_pgno_t, void *, DBT *));
 };
 
 /*
@@ -207,7 +205,7 @@ struct __mpool {
        size_t      htab_buckets;       /* Number of hash table entries. */
 
        DB_LSN      lsn;                /* Maximum checkpoint LSN. */
-       int         lsn_cnt;            /* Checkpoint buffers left to write. */
+       u_int32_t   lsn_cnt;            /* Checkpoint buffers left to write. */
 
        DB_MPOOL_STAT stat;             /* Global mpool statistics. */
 
@@ -225,7 +223,9 @@ struct __mpoolfile {
        u_int32_t ref;                  /* Reference count. */
 
        int       ftype;                /* File type. */
-       int       lsn_off;              /* Page's LSN offset. */
+
+       int32_t   lsn_off;              /* Page's LSN offset. */
+       u_int32_t clear_len;            /* Bytes to clear on page create. */
 
        size_t    path_off;             /* File name location. */
        size_t    fileid_off;           /* File identification location. */
@@ -233,9 +233,10 @@ struct __mpoolfile {
        size_t    pgcookie_len;         /* Pgin/pgout cookie length. */
        size_t    pgcookie_off;         /* Pgin/pgout cookie location. */
 
-       int       lsn_cnt;              /* Checkpoint buffers left to write. */
+       u_int32_t lsn_cnt;              /* Checkpoint buffers left to write. */
 
        db_pgno_t last_pgno;            /* Last page in the file. */
+       db_pgno_t orig_last_pgno;       /* Original last page in the file. */
 
 #define        MP_CAN_MMAP     0x01            /* If the file can be mmap'd. */
 #define        MP_TEMP         0x02            /* Backing file is a temporary. */
index 1928820..3650839 100644 (file)
@@ -7,13 +7,13 @@ int __memp_pgread __P((DB_MPOOLFILE *, BH *, int));
 int __memp_pgwrite __P((DB_MPOOLFILE *, BH *, int *, int *));
 int __memp_pg __P((DB_MPOOLFILE *, BH *, int));
 void __memp_bhfree __P((DB_MPOOL *, MPOOLFILE *, BH *, int));
-int __memp_fopen __P((DB_MPOOL *, MPOOLFILE *, const char *, int,
-   int, int, size_t, int, DBT *, u_int8_t *, int, DB_MPOOLFILE **));
+int __memp_fopen __P((DB_MPOOL *, MPOOLFILE *, const char *,
+   u_int32_t, int, size_t, int, DB_MPOOL_FINFO *, DB_MPOOLFILE **));
 char * __memp_fn __P((DB_MPOOLFILE *));
 char * __memp_fns __P((DB_MPOOL *, MPOOLFILE *));
-void __memp_debug __P((DB_MPOOL *, FILE *, int));
+void __memp_dump_region __P((DB_MPOOL *, char *, FILE *));
 int __memp_ralloc __P((DB_MPOOL *, size_t, size_t *, void *));
 int __memp_ropen
-   __P((DB_MPOOL *, const char *, size_t, int, int));
-int __memp_rclose __P((DB_MPOOL *));
+   __P((DB_MPOOL *, const char *, size_t, int, int, u_int32_t));
+int __mp_xxx_fd __P((DB_MPOOLFILE *, int *));
 #endif /* _mp_ext_h_ */
index f0e68f3..b48da5d 100644 (file)
@@ -1,7 +1,7 @@
 /* DO NOT EDIT: automatically built by dist/distrib. */
 #ifndef _mutex_ext_h_
 #define _mutex_ext_h_
-void __db_mutex_init __P((db_mutex_t *, u_int32_t));
+int __db_mutex_init __P((db_mutex_t *, u_int32_t));
 int __db_mutex_lock __P((db_mutex_t *, int));
 int __db_mutex_unlock __P((db_mutex_t *, int));
 #endif /* _mutex_ext_h_ */
index 9c66a24..889a45a 100644 (file)
@@ -2,23 +2,29 @@
 #ifndef _os_ext_h_
 #define _os_ext_h_
 int __db_abspath __P((const char *));
+char *__db_strdup __P((const char *));
 void *__db_calloc __P((size_t, size_t));
 void *__db_malloc __P((size_t));
 void *__db_realloc __P((void *, size_t));
-int __os_oldwin __P((void));
 int __os_dirlist __P((const char *, char ***, int *));
 void __os_dirfree __P((char **, int));
 int __db_fileid __P((DB_ENV *, const char *, int, u_int8_t *));
 int __db_fsync __P((int));
-int __os_map __P((int, size_t, int, int, void **));
-int __os_unmap __P((void *, size_t));
-int __db_oflags __P((int));
-int __db_open __P((const char *, int, int, int, int *));
+int __db_mapanon_ok __P((int));
+int __db_mapinit __P((void));
+int __db_mapregion __P((char *, REGINFO *));
+int __db_unmapregion __P((REGINFO *));
+int __db_unlinkregion __P((char *, REGINFO *));
+int __db_mapfile __P((char *, int, size_t, int, void **));
+int __db_unmapfile __P((void *, size_t));
+u_int32_t __db_oflags __P((int));
+int __db_omode __P((const char *));
+int __db_open __P((const char *, u_int32_t, u_int32_t, int, int *));
 int __db_close __P((int));
 char *__db_rpath __P((const char *));
 int __db_read __P((int, void *, size_t, ssize_t *));
 int __db_write __P((int, void *, size_t, ssize_t *));
-int __os_seek __P((int, size_t, db_pgno_t, u_long, int));
+int __os_seek __P((int, size_t, db_pgno_t, u_int32_t, int, int));
 int __os_sleep __P((u_long, u_long));
 int __os_spin __P((void));
 int __os_exists __P((const char *, int *));
index b825fed..12794d5 100644 (file)
@@ -1,40 +1,40 @@
 /*-
  * See the file LICENSE for redistribution information.
  *
- * Copyright (c) 1997
+ * Copyright (c) 1997, 1998
  *     Sleepycat Software.  All rights reserved.
  *
- *     @(#)os_func.h   10.5 (Sleepycat) 12/4/97
+ *     @(#)os_func.h   10.8 (Sleepycat) 4/19/98
  */
 
 /* Calls which can be replaced by the application. */
 struct __db_jumptab {
-       int     (*db_close) __P((int));                 /* DB_FUNC_CLOSE */
-       void    (*db_dirfree) __P((char **, int));      /* DB_FUNC_DIRFREE */
-       int     (*db_dirlist)                           /* DB_FUNC_DIRLIST */
+       int     (*j_close) __P((int));                  /* DB_FUNC_CLOSE */
+       void    (*j_dirfree) __P((char **, int));       /* DB_FUNC_DIRFREE */
+       int     (*j_dirlist)                            /* DB_FUNC_DIRLIST */
                    __P((const char *, char ***, int *));
-       int     (*db_exists)                            /* DB_FUNC_EXISTS */
+       int     (*j_exists)                             /* DB_FUNC_EXISTS */
                    __P((const char *, int *));
-       void    (*db_free) __P((void *));               /* DB_FUNC_FREE */
-       int     (*db_fsync) __P((int));                 /* DB_FUNC_FSYNC */
-       int     (*db_ioinfo) __P((const char *,         /* DB_FUNC_IOINFO */
+       void    (*j_free) __P((void *));                /* DB_FUNC_FREE */
+       int     (*j_fsync) __P((int));                  /* DB_FUNC_FSYNC */
+       int     (*j_ioinfo) __P((const char *,          /* DB_FUNC_IOINFO */
                    int, u_int32_t *, u_int32_t *, u_int32_t *));
-       void   *(*db_malloc) __P((size_t));             /* DB_FUNC_MALLOC */
-       int     (*db_map)                               /* DB_FUNC_MAP */
-                   __P((int, size_t, int, int, void **));
-       int     (*db_open)                              /* DB_FUNC_OPEN */
+       void   *(*j_malloc) __P((size_t));              /* DB_FUNC_MALLOC */
+       int     (*j_map)                                /* DB_FUNC_MAP */
+                   __P((char *, int, size_t, int, int, int, void **));
+       int     (*j_open)                               /* DB_FUNC_OPEN */
                    __P((const char *, int, ...));
-       ssize_t (*db_read) __P((int, void *, size_t));  /* DB_FUNC_READ */
-       void   *(*db_realloc) __P((void *, size_t));    /* DB_FUNC_REALLOC */
-       int     (*db_seek)                              /* DB_FUNC_SEEK */
-                   __P((int, size_t, db_pgno_t, u_long, int));
-       int     (*db_sleep) __P((u_long, u_long));      /* DB_FUNC_SLEEP */
-       char   *(*db_strdup) __P((const char *));       /* DB_FUNC_STRDUP */
-       int     (*db_unlink) __P((const char *));       /* DB_FUNC_UNLINK */
-       int     (*db_unmap) __P((void *, size_t));      /* DB_FUNC_UNMAP */
-       ssize_t (*db_write)                             /* DB_FUNC_WRITE */
+       ssize_t (*j_read) __P((int, void *, size_t));   /* DB_FUNC_READ */
+       void   *(*j_realloc) __P((void *, size_t));     /* DB_FUNC_REALLOC */
+       int     (*j_runlink) __P((char *));             /* DB_FUNC_RUNLINK */
+       int     (*j_seek)                               /* DB_FUNC_SEEK */
+                   __P((int, size_t, db_pgno_t, u_int32_t, int, int));
+       int     (*j_sleep) __P((u_long, u_long));       /* DB_FUNC_SLEEP */
+       int     (*j_unlink) __P((const char *));        /* DB_FUNC_UNLINK */
+       int     (*j_unmap) __P((void *, size_t));       /* DB_FUNC_UNMAP */
+       ssize_t (*j_write)                              /* DB_FUNC_WRITE */
                    __P((int, const void *, size_t));
-       int     (*db_yield) __P((void));                /* DB_FUNC_YIELD */
+       int     (*j_yield) __P((void));                 /* DB_FUNC_YIELD */
 };
 
 extern struct __db_jumptab __db_jump;
@@ -43,7 +43,7 @@ extern struct __db_jumptab __db_jump;
  * Names used by DB to call through the jump table.
  *
  * The naming scheme goes like this: if the functionality the application can
- * replace is the same as the DB functionality, e.g., calloc, or dirlist, then
+ * replace is the same as the DB functionality, e.g., malloc, or dirlist, then
  * we use the name __db_XXX, and the application is expected to replace the
  * complete functionality, which may or may not map directly to an ANSI C or
  * POSIX 1003.1 interface.  If the functionality that the aplication replaces
@@ -53,20 +53,17 @@ extern struct __db_jumptab __db_jump;
  * part of DB is the only code that should use the __os_XXX names, all other
  * parts of DB should be calling __db_XXX functions.
  */
-#define        __os_close      __db_jump.db_close      /* __db_close is a wrapper. */
-#define        __db_dirfree    __db_jump.db_dirfree
-#define        __db_dirlist    __db_jump.db_dirlist
-#define        __db_exists     __db_jump.db_exists
-#define        __db_free       __db_jump.db_free
-#define        __os_fsync      __db_jump.db_fsync      /* __db_fsync is a wrapper. */
-#define        __db_ioinfo     __db_jump.db_ioinfo
-#define        __db_map        __db_jump.db_map
-#define        __os_open       __db_jump.db_open       /* __db_open is a wrapper. */
-#define        __os_read       __db_jump.db_read       /* __db_read is a wrapper. */
-#define        __db_seek       __db_jump.db_seek
-#define        __db_sleep      __db_jump.db_sleep
-#define        __db_strdup     __db_jump.db_strdup
-#define        __os_unlink     __db_jump.db_unlink     /* __db_unlink is a wrapper. */
-#define        __db_unmap      __db_jump.db_unmap
-#define        __os_write      __db_jump.db_write      /* __db_write is a wrapper. */
-#define        __db_yield      __db_jump.db_yield
+#define        __os_close      __db_jump.j_close       /* __db_close is a wrapper. */
+#define        __db_dirfree    __db_jump.j_dirfree
+#define        __db_dirlist    __db_jump.j_dirlist
+#define        __db_exists     __db_jump.j_exists
+#define        __db_free       __db_jump.j_free
+#define        __os_fsync      __db_jump.j_fsync       /* __db_fsync is a wrapper. */
+#define        __db_ioinfo     __db_jump.j_ioinfo
+#define        __os_open       __db_jump.j_open        /* __db_open is a wrapper. */
+#define        __os_read       __db_jump.j_read        /* __db_read is a wrapper. */
+#define        __db_seek       __db_jump.j_seek
+#define        __db_sleep      __db_jump.j_sleep
+#define        __os_unlink     __db_jump.j_unlink      /* __db_unlink is a wrapper. */
+#define        __os_write      __db_jump.j_write       /* __db_write is a wrapper. */
+#define        __db_yield      __db_jump.j_yield
index 0909c86..f606eb0 100644 (file)
@@ -1,6 +1,6 @@
 /*     BSDI $Id$       */
 
-/* 
+/*
  * Copyright (c) 1991, 1993
  *     The Regents of the University of California.  All rights reserved.
  *
index c596d33..00e5d76 100644 (file)
@@ -1,10 +1,10 @@
 /*-
  * See the file LICENSE for redistribution information.
  *
- * Copyright (c) 1996, 1997
+ * Copyright (c) 1996, 1997, 1998
  *     Sleepycat Software.  All rights reserved.
  *
- *     @(#)shqueue.h   8.12 (Sleepycat) 9/10/97
+ *     @(#)shqueue.h   8.13 (Sleepycat) 4/10/98
  */
 #ifndef        _SYS_SHQUEUE_H_
 #define        _SYS_SHQUEUE_H_
index c64ac3f..a2512ed 100644 (file)
@@ -1,10 +1,10 @@
 /*-
  * See the file LICENSE for redistribution information.
  *
- * Copyright (c) 1996, 1997
+ * Copyright (c) 1996, 1997, 1998
  *     Sleepycat Software.  All rights reserved.
  *
- *     @(#)txn.h       10.11 (Sleepycat) 10/25/97
+ *     @(#)txn.h       10.15 (Sleepycat) 4/21/98
  */
 #ifndef        _TXN_H_
 #define        _TXN_H_
@@ -52,12 +52,11 @@ struct __db_txnmgr {
        TAILQ_HEAD(_chain, __db_txn)    txn_chain;
 
 /* These fields are not protected. */
+       REGINFO         reginfo;        /* Region information. */
        DB_ENV          *dbenv;         /* Environment. */
        int (*recover)                  /* Recovery dispatch routine */
            __P((DB_LOG *, DBT *, DB_LSN *, int, void *));
-       int              fd;            /* mapped file descriptor */
-       u_int            flags;         /* DB_TXN_NOSYNC, DB_THREAD */
-       size_t           reg_size;      /* how large we think the region is */
+       u_int32_t        flags;         /* DB_TXN_NOSYNC, DB_THREAD */
        DB_TXNREGION    *region;        /* address of shared memory region */
        void            *mem;           /* address of the shalloc space */
 };
@@ -102,17 +101,16 @@ struct __db_txnregion {
                (void)__db_mutex_unlock((tmgrp)->mutexp, -1)
 
 #define        LOCK_TXNREGION(tmgrp)                                           \
-       (void)__db_mutex_lock(&(tmgrp)->region->hdr.lock, (tmgrp)->fd)
+       (void)__db_mutex_lock(&(tmgrp)->region->hdr.lock, (tmgrp)->reginfo.fd)
 #define        UNLOCK_TXNREGION(tmgrp)                                         \
-       (void)__db_mutex_unlock(&(tmgrp)->region->hdr.lock, (tmgrp)->fd)
+       (void)__db_mutex_unlock(&(tmgrp)->region->hdr.lock, (tmgrp)->reginfo.fd)
 
 /*
  * Log record types.
  */
-#define        TXN_BEGIN       1
-#define        TXN_COMMIT      2
-#define        TXN_PREPARE     3
-#define        TXN_CHECKPOINT  4
+#define        TXN_COMMIT      1
+#define        TXN_PREPARE     2
+#define        TXN_CHECKPOINT  3
 
 #include "txn_auto.h"
 #include "txn_ext.h"
index 0846d3c..3d20e0d 100644 (file)
@@ -1,28 +1,21 @@
 /*-
  * See the file LICENSE for redistribution information.
  *
- * Copyright (c) 1996, 1997
+ * Copyright (c) 1996, 1997, 1998
  *     Sleepycat Software.  All rights reserved.
  */
 
 #include "config.h"
 
 #ifndef lint
-static const char sccsid[] = "@(#)lock.c       10.43 (Sleepycat) 1/8/98";
+static const char sccsid[] = "@(#)lock.c       10.52 (Sleepycat) 5/10/98";
 #endif /* not lint */
 
 #ifndef NO_SYSTEM_INCLUDES
 #include <sys/types.h>
-#include <sys/mman.h>
-#include <sys/stat.h>
 
 #include <errno.h>
-#include <fcntl.h>
-#include <stddef.h>
-#include <stdio.h>
-#include <stdlib.h>
 #include <string.h>
-#include <unistd.h>
 #endif
 
 #include "db_int.h"
@@ -34,248 +27,15 @@ static const char sccsid[] = "@(#)lock.c   10.43 (Sleepycat) 1/8/98";
 #include "db_am.h"
 
 static void __lock_checklocker __P((DB_LOCKTAB *, struct __db_lock *, int));
-static int  __lock_count_locks __P((DB_LOCKREGION *));
-static int  __lock_count_objs __P((DB_LOCKREGION *));
-static int  __lock_create __P((const char *, int, DB_ENV *));
 static void __lock_freeobj __P((DB_LOCKTAB *, DB_LOCKOBJ *));
-static int  __lock_get_internal __P((DB_LOCKTAB *, u_int32_t, int, const DBT *,
-    db_lockmode_t, struct __db_lock **));
-static int  __lock_grow_region __P((DB_LOCKTAB *, int, size_t));
+static int  __lock_get_internal __P((DB_LOCKTAB *, u_int32_t, u_int32_t,
+    const DBT *, db_lockmode_t, struct __db_lock **));
 static int  __lock_put_internal __P((DB_LOCKTAB *, struct __db_lock *, int));
 static void __lock_remove_waiter
     __P((DB_LOCKTAB *, DB_LOCKOBJ *, struct __db_lock *, db_status_t));
-static void __lock_reset_region __P((DB_LOCKTAB *));
-static int  __lock_validate_region __P((DB_LOCKTAB *));
-#ifdef DEBUG
-static void __lock_dump_locker __P((DB_LOCKTAB *, DB_LOCKOBJ *));
-static void __lock_dump_object __P((DB_LOCKTAB *, DB_LOCKOBJ *));
-static void __lock_printlock __P((DB_LOCKTAB *, struct __db_lock *, int));
-#endif
-
-/*
- * Create and initialize a lock region in shared memory.
- */
-
-/*
- * __lock_create --
- *     Create the lock region.  Returns an errno.  In most cases,
- * the errno should be that returned by __db_ropen, in which case
- * an EAGAIN means that we should retry, and an EEXIST means that
- * the region exists and we didn't need to create it.  Any other
- * sort of errno should be treated as a system error, leading to a
- * failure of the original interface call.
- */
-static int
-__lock_create(path, mode, dbenv)
-       const char *path;
-       int mode;
-       DB_ENV *dbenv;
-{
-       struct __db_lock *lp;
-       struct lock_header *tq_head;
-       struct obj_header *obj_head;
-       DB_LOCKOBJ *op;
-       DB_LOCKREGION *lrp;
-       u_int maxlocks;
-       u_int32_t i;
-       int fd, lock_modes, nelements, ret;
-       const u_int8_t *conflicts;
-       u_int8_t *curaddr;
-
-       maxlocks = dbenv == NULL || dbenv->lk_max == 0 ?
-           DB_LOCK_DEFAULT_N : dbenv->lk_max;
-       lock_modes = dbenv == NULL || dbenv->lk_modes == 0 ?
-           DB_LOCK_RW_N : dbenv->lk_modes;
-       conflicts = dbenv == NULL || dbenv->lk_conflicts == NULL ?
-           db_rw_conflicts : dbenv->lk_conflicts;
-
-       if ((ret =
-           __db_rcreate(dbenv, DB_APP_NONE, path, DB_DEFAULT_LOCK_FILE, mode,
-           LOCK_REGION_SIZE(lock_modes, maxlocks, __db_tablesize(maxlocks)),
-           0, &fd, &lrp)) != 0)
-               return (ret);
-
-       /* Region exists; now initialize it. */
-       lrp->table_size = __db_tablesize(maxlocks);
-       lrp->magic = DB_LOCKMAGIC;
-       lrp->version = DB_LOCKVERSION;
-       lrp->id = 0;
-       lrp->maxlocks = maxlocks;
-       lrp->need_dd = 0;
-       lrp->detect = DB_LOCK_NORUN;
-       lrp->numobjs = maxlocks;
-       lrp->nlockers = 0;
-       lrp->mem_bytes = ALIGN(STRING_SIZE(maxlocks), sizeof(size_t));
-       lrp->increment = lrp->hdr.size / 2;
-       lrp->nmodes = lock_modes;
-       lrp->nconflicts = 0;
-       lrp->nrequests = 0;
-       lrp->nreleases = 0;
-       lrp->ndeadlocks = 0;
-
-       /*
-        * As we write the region, we've got to maintain the alignment
-        * for the structures that follow each chunk.  This information
-        * ends up being encapsulated both in here as well as in the
-        * lock.h file for the XXX_SIZE macros.
-        */
-       /* Initialize conflict matrix. */
-       curaddr = (u_int8_t *)lrp + sizeof(DB_LOCKREGION);
-       memcpy(curaddr, conflicts, lock_modes * lock_modes);
-       curaddr += lock_modes * lock_modes;
-
-       /*
-        * Initialize hash table.
-        */
-       curaddr = (u_int8_t *)ALIGNP(curaddr, LOCK_HASH_ALIGN);
-       lrp->hash_off = curaddr - (u_int8_t *)lrp;
-       nelements = lrp->table_size;
-       __db_hashinit(curaddr, nelements);
-       curaddr += nelements * sizeof(DB_HASHTAB);
-
-       /*
-        * Initialize locks onto a free list. Since locks contains mutexes,
-        * we need to make sure that each lock is aligned on a MUTEX_ALIGNMENT
-        * boundary.
-        */
-       curaddr = (u_int8_t *)ALIGNP(curaddr, MUTEX_ALIGNMENT);
-       tq_head = &lrp->free_locks;
-       SH_TAILQ_INIT(tq_head);
-
-       for (i = 0; i++ < maxlocks;
-           curaddr += ALIGN(sizeof(struct __db_lock), MUTEX_ALIGNMENT)) {
-               lp = (struct __db_lock *)curaddr;
-               lp->status = DB_LSTAT_FREE;
-               SH_TAILQ_INSERT_HEAD(tq_head, lp, links, __db_lock);
-       }
-
-       /* Initialize objects onto a free list.  */
-       obj_head = &lrp->free_objs;
-       SH_TAILQ_INIT(obj_head);
-
-       for (i = 0; i++ < maxlocks; curaddr += sizeof(DB_LOCKOBJ)) {
-               op = (DB_LOCKOBJ *)curaddr;
-               SH_TAILQ_INSERT_HEAD(obj_head, op, links, __db_lockobj);
-       }
-
-       /*
-        * Initialize the string space; as for all shared memory allocation
-        * regions, this requires size_t alignment, since we store the
-        * lengths of malloc'd areas in the area..
-        */
-       curaddr = (u_int8_t *)ALIGNP(curaddr, sizeof(size_t));
-       lrp->mem_off = curaddr - (u_int8_t *)lrp;
-       __db_shalloc_init(curaddr, lrp->mem_bytes);
-
-       /* Release the lock. */
-       (void)__db_mutex_unlock(&lrp->hdr.lock, fd);
-
-       /* Now unmap the region. */
-       if ((ret = __db_rclose(dbenv, fd, lrp)) != 0) {
-               (void)lock_unlink(path, 1 /* force */, dbenv);
-               return (ret);
-       }
-
-       return (0);
-}
 
 int
-lock_open(path, flags, mode, dbenv, ltp)
-       const char *path;
-       int flags, mode;
-       DB_ENV *dbenv;
-       DB_LOCKTAB **ltp;
-{
-       DB_LOCKTAB *lt;
-       int ret, retry_cnt;
-
-       /* Validate arguments. */
-#ifdef HAVE_SPINLOCKS
-#define        OKFLAGS (DB_CREATE | DB_THREAD)
-#else
-#define        OKFLAGS (DB_CREATE)
-#endif
-       if ((ret = __db_fchk(dbenv, "lock_open", flags, OKFLAGS)) != 0)
-               return (ret);
-
-       /*
-        * Create the lock table structure.
-        */
-       if ((lt = (DB_LOCKTAB *)__db_calloc(1, sizeof(DB_LOCKTAB))) == NULL) {
-               __db_err(dbenv, "%s", strerror(ENOMEM));
-               return (ENOMEM);
-       }
-       lt->dbenv = dbenv;
-
-       /*
-        * Now, create the lock region if it doesn't already exist.
-        */
-       retry_cnt = 0;
-retry: if (LF_ISSET(DB_CREATE) &&
-           (ret = __lock_create(path, mode, dbenv)) != 0)
-               if (ret == EAGAIN && ++retry_cnt < 3) {
-                       (void)__db_sleep(1, 0);
-                       goto retry;
-               } else if (ret == EEXIST) /* We did not create the region */
-                       LF_CLR(DB_CREATE);
-               else
-                       goto out;
-
-       /*
-        * Finally, open the region, map it in, and increment the
-        * reference count.
-        */
-       retry_cnt = 0;
-retry1:        if ((ret = __db_ropen(dbenv, DB_APP_NONE, path, DB_DEFAULT_LOCK_FILE,
-           LF_ISSET(~(DB_CREATE | DB_THREAD)), &lt->fd, &lt->region)) != 0) {
-               if (ret == EAGAIN && ++retry_cnt < 3) {
-                       (void)__db_sleep(1, 0);
-                       goto retry1;
-               }
-               goto out;
-        }
-
-       if (lt->region->magic != DB_LOCKMAGIC) {
-               __db_err(dbenv, "lock_open: Bad magic number");
-               ret = EINVAL;
-               goto out;
-       }
-
-       /* Check for automatic deadlock detection. */
-       if (dbenv->lk_detect != DB_LOCK_NORUN) {
-               if (lt->region->detect != DB_LOCK_NORUN &&
-                   dbenv->lk_detect != DB_LOCK_DEFAULT &&
-                   lt->region->detect != dbenv->lk_detect) {
-                       __db_err(dbenv,
-                           "lock_open: incompatible deadlock detector mode");
-                       ret = EINVAL;
-                       goto out;
-               }
-               if (lt->region->detect == DB_LOCK_NORUN)
-                       lt->region->detect = dbenv->lk_detect;
-       }
-
-       /* Set up remaining pointers into region. */
-       lt->conflicts = (u_int8_t *)lt->region + sizeof(DB_LOCKREGION);
-       lt->hashtab =
-           (DB_HASHTAB *)((u_int8_t *)lt->region + lt->region->hash_off);
-       lt->mem = (void *)((u_int8_t *)lt->region + lt->region->mem_off);
-       lt->reg_size = lt->region->hdr.size;
-
-       *ltp = lt;
-       return (0);
-
-/* Error handling. */
-out:   if (lt->region != NULL)
-               (void)__db_rclose(lt->dbenv, lt->fd, lt->region);
-       if (LF_ISSET(DB_CREATE))
-               (void)lock_unlink(path, 1, lt->dbenv);
-       __db_free(lt);
-       return (ret);
-}
-
-int
-lock_id (lt, idp)
+lock_id(lt, idp)
        DB_LOCKTAB *lt;
        u_int32_t *idp;
 {
@@ -294,8 +54,8 @@ lock_id (lt, idp)
 int
 lock_vec(lt, locker, flags, list, nlist, elistp)
        DB_LOCKTAB *lt;
-       u_int32_t locker;
-       int flags, nlist;
+       u_int32_t locker, flags;
+       int nlist;
        DB_LOCKREQ *list, **elistp;
 {
        struct __db_lock *lp;
@@ -345,7 +105,7 @@ lock_vec(lt, locker, flags, list, nlist, elistp)
                        for (lp = SH_LIST_FIRST(&sh_locker->heldby, __db_lock);
                            lp != NULL;
                            lp = SH_LIST_FIRST(&sh_locker->heldby, __db_lock)) {
-                               if ((ret = __lock_put_internal(lt, lp, 0)) != 0)
+                               if ((ret = __lock_put_internal(lt, lp, 1)) != 0)
                                        break;
                        }
                        __lock_freeobj(lt, sh_locker);
@@ -436,8 +196,7 @@ lock_vec(lt, locker, flags, list, nlist, elistp)
 int
 lock_get(lt, locker, flags, obj, lock_mode, lock)
        DB_LOCKTAB *lt;
-       u_int32_t locker;
-       int flags;
+       u_int32_t locker, flags;
        const DBT *obj;
        db_lockmode_t lock_mode;
        DB_LOCK *lock;
@@ -496,35 +255,6 @@ lock_put(lt, lock)
        return (ret);
 }
 
-int
-lock_close(lt)
-       DB_LOCKTAB *lt;
-{
-       int ret;
-
-       if ((ret = __db_rclose(lt->dbenv, lt->fd, lt->region)) != 0)
-               return (ret);
-
-       /* Free lock table. */
-       __db_free(lt);
-       return (0);
-}
-
-int
-lock_unlink(path, force, dbenv)
-       const char *path;
-       int force;
-       DB_ENV *dbenv;
-{
-       return (__db_runlink(dbenv,
-           DB_APP_NONE, path, DB_DEFAULT_LOCK_FILE, force));
-}
-
-/*
- * XXX This looks like it could be void, but I'm leaving it returning
- * an int because I think it will have to when we go through and add
- * the appropriate error checking for the EINTR on mutexes.
- */
 static int
 __lock_put_internal(lt, lockp, do_all)
        DB_LOCKTAB *lt;
@@ -593,7 +323,7 @@ __lock_put_internal(lt, lockp, do_all)
                SH_TAILQ_INSERT_TAIL(&sh_obj->holders, lp_w, links);
 
                /* Wake up waiter. */
-               (void)__db_mutex_unlock(&lp_w->mutex, lt->fd);
+               (void)__db_mutex_unlock(&lp_w->mutex, lt->reginfo.fd);
                state_changed = 1;
        }
 
@@ -626,8 +356,7 @@ __lock_put_internal(lt, lockp, do_all)
 static int
 __lock_get_internal(lt, locker, flags, obj, lock_mode, lockp)
        DB_LOCKTAB *lt;
-       u_int32_t locker;
-       int flags;
+       u_int32_t locker, flags;
        const DBT *obj;
        db_lockmode_t lock_mode;
        struct __db_lock **lockp;
@@ -741,7 +470,7 @@ __lock_get_internal(lt, locker, flags, obj, lock_mode, lockp)
         */
        (void)__db_mutex_init(&newl->mutex,
            MUTEX_LOCK_OFFSET(lt->region, &newl->mutex));
-       (void)__db_mutex_lock(&newl->mutex, lt->fd);
+       (void)__db_mutex_lock(&newl->mutex, lt->reginfo.fd);
 
        /*
         * Now, insert the lock onto its locker's list.
@@ -772,7 +501,7 @@ __lock_get_internal(lt, locker, flags, obj, lock_mode, lockp)
                if (lrp->detect != DB_LOCK_NORUN)
                        ret = lock_detect(lt, 0, lrp->detect);
 
-               (void)__db_mutex_lock(&newl->mutex, lt->fd);
+               (void)__db_mutex_lock(&newl->mutex, lt->reginfo.fd);
 
                LOCK_LOCKREGION(lt);
                if (newl->status != DB_LSTAT_PENDING) {
@@ -802,306 +531,6 @@ __lock_get_internal(lt, locker, flags, obj, lock_mode, lockp)
 }
 
 /*
- * This is called at every interface to verify if the region
- * has changed size, and if so, to remap the region in and
- * reset the process pointers.
- */
-static int
-__lock_validate_region(lt)
-       DB_LOCKTAB *lt;
-{
-       int ret;
-
-       if (lt->reg_size == lt->region->hdr.size)
-               return (0);
-
-       /* Grow the region. */
-       if ((ret = __db_rremap(lt->dbenv, lt->region,
-           lt->reg_size, lt->region->hdr.size, lt->fd, &lt->region)) != 0)
-               return (ret);
-
-       __lock_reset_region(lt);
-
-       return (0);
-}
-
-/*
- * We have run out of space; time to grow the region.
- */
-static int
-__lock_grow_region(lt, which, howmuch)
-       DB_LOCKTAB *lt;
-       int which;
-       size_t howmuch;
-{
-       struct __db_lock *newl;
-       struct lock_header *lock_head;
-       struct obj_header *obj_head;
-       DB_LOCKOBJ *op;
-       DB_LOCKREGION *lrp;
-       float lock_ratio, obj_ratio;
-       size_t incr, oldsize, used;
-       u_int32_t i, newlocks, newmem, newobjs;
-       int ret, usedlocks, usedmem, usedobjs;
-       u_int8_t *curaddr;
-
-       lrp = lt->region;
-       oldsize = lrp->hdr.size;
-       incr = lrp->increment;
-
-       /* Figure out how much of each sort of space we have. */
-       usedmem = lrp->mem_bytes - __db_shalloc_count(lt->mem);
-       usedobjs = lrp->numobjs - __lock_count_objs(lrp);
-       usedlocks = lrp->maxlocks - __lock_count_locks(lrp);
-
-       /*
-        * Figure out what fraction of the used space belongs to each
-        * different type of "thing" in the region.  Then partition the
-        * new space up according to this ratio.
-        */
-       used = usedmem +
-           usedlocks * ALIGN(sizeof(struct __db_lock), MUTEX_ALIGNMENT) +
-           usedobjs * sizeof(DB_LOCKOBJ);
-
-       lock_ratio = usedlocks *
-           ALIGN(sizeof(struct __db_lock), MUTEX_ALIGNMENT) / (float)used;
-       obj_ratio = usedobjs * sizeof(DB_LOCKOBJ) / (float)used;
-
-       newlocks = (u_int32_t)(lock_ratio *
-           incr / ALIGN(sizeof(struct __db_lock), MUTEX_ALIGNMENT));
-       newobjs = (u_int32_t)(obj_ratio * incr / sizeof(DB_LOCKOBJ));
-       newmem = incr -
-           (newobjs * sizeof(DB_LOCKOBJ) +
-           newlocks * ALIGN(sizeof(struct __db_lock), MUTEX_ALIGNMENT));
-
-       /*
-        * Make sure we allocate enough memory for the object being
-        * requested.
-        */
-       switch (which) {
-               case DB_LOCK_LOCK:
-                       if (newlocks == 0) {
-                               newlocks = 10;
-                               incr += newlocks * sizeof(struct __db_lock);
-                       }
-                       break;
-               case DB_LOCK_OBJ:
-                       if (newobjs == 0) {
-                               newobjs = 10;
-                               incr += newobjs * sizeof(DB_LOCKOBJ);
-                       }
-                       break;
-               case DB_LOCK_MEM:
-                       if (newmem < howmuch * 2) {
-                               incr += howmuch * 2 - newmem;
-                               newmem = howmuch * 2;
-                       }
-                       break;
-       }
-
-       newmem += ALIGN(incr, sizeof(size_t)) - incr;
-       incr = ALIGN(incr, sizeof(size_t));
-
-       /*
-        * Since we are going to be allocating locks at the beginning of the
-        * new chunk, we need to make sure that the chunk is MUTEX_ALIGNMENT
-        * aligned.  We did not guarantee this when we created the region, so
-        * we may need to pad the old region by extra bytes to ensure this
-        * alignment.
-        */
-       incr += ALIGN(oldsize, MUTEX_ALIGNMENT) - oldsize;
-
-       __db_err(lt->dbenv,
-           "Growing lock region: %lu locks %lu objs %lu bytes",
-           (u_long)newlocks, (u_long)newobjs, (u_long)newmem);
-
-       if ((ret = __db_rgrow(lt->dbenv, lt->fd, incr)) != 0)
-               return (ret);
-       if ((ret = __db_rremap(lt->dbenv,
-           lt->region, oldsize, oldsize + incr, lt->fd, &lt->region)) != 0)
-               return (ret);
-       __lock_reset_region(lt);
-
-       /* Update region parameters. */
-       lrp = lt->region;
-       lrp->increment = incr << 1;
-       lrp->maxlocks += newlocks;
-       lrp->numobjs += newobjs;
-       lrp->mem_bytes += newmem;
-
-       curaddr = (u_int8_t *)lrp + oldsize;
-       curaddr = (u_int8_t *)ALIGNP(curaddr, MUTEX_ALIGNMENT);
-
-       /* Put new locks onto the free list. */
-       lock_head = &lrp->free_locks;
-       for (i = 0; i++ < newlocks;
-           curaddr += ALIGN(sizeof(struct __db_lock), MUTEX_ALIGNMENT)) {
-               newl = (struct __db_lock *)curaddr;
-               SH_TAILQ_INSERT_HEAD(lock_head, newl, links, __db_lock);
-       }
-
-       /* Put new objects onto the free list.  */
-       obj_head = &lrp->free_objs;
-       for (i = 0; i++ < newobjs; curaddr += sizeof(DB_LOCKOBJ)) {
-               op = (DB_LOCKOBJ *)curaddr;
-               SH_TAILQ_INSERT_HEAD(obj_head, op, links, __db_lockobj);
-       }
-
-       *((size_t *)curaddr) = newmem - sizeof(size_t);
-       curaddr += sizeof(size_t);
-       __db_shalloc_free(lt->mem, curaddr);
-
-       return (0);
-}
-
-#ifdef DEBUG
-/*
- * __lock_dump_region --
- *
- * PUBLIC: void __lock_dump_region __P((DB_LOCKTAB *, u_int));
- */
-void
-__lock_dump_region(lt, flags)
-       DB_LOCKTAB *lt;
-       u_int flags;
-{
-       struct __db_lock *lp;
-       DB_LOCKOBJ *op;
-       DB_LOCKREGION *lrp;
-       u_int32_t i, j;
-
-       lrp = lt->region;
-
-       printf("Lock region parameters\n");
-       printf("%s:0x%x\t%s:%lu\t%s:%lu\t%s:%lu\n%s:%lu\t%s:%lu\t%s:%lu\t\n",
-           "magic      ", lrp->magic,
-           "version    ", (u_long)lrp->version,
-           "processes  ", (u_long)lrp->hdr.refcnt,
-           "maxlocks   ", (u_long)lrp->maxlocks,
-           "table size ", (u_long)lrp->table_size,
-           "nmodes     ", (u_long)lrp->nmodes,
-           "numobjs    ", (u_long)lrp->numobjs);
-       printf("%s:%lu\t%s:%lu\t%s:%lu\n%s:%lu\t%s:%lu\t%s:%lu\n",
-           "size       ", (u_long)lrp->hdr.size,
-           "nlockers   ", (u_long)lrp->nlockers,
-           "hash_off   ", (u_long)lrp->hash_off,
-           "increment  ", (u_long)lrp->increment,
-           "mem_off    ", (u_long)lrp->mem_off,
-           "mem_bytes  ", (u_long)lrp->mem_bytes);
-#ifndef HAVE_SPINLOCKS
-       printf("Mutex: off %lu", (u_long)lrp->hdr.lock.off);
-#endif
-       printf(" waits %lu nowaits %lu",
-           (u_long)lrp->hdr.lock.mutex_set_wait,
-           (u_long)lrp->hdr.lock.mutex_set_nowait);
-       printf("\n%s:%lu\t%s:%lu\t%s:%lu\t%s:%lu\n",
-           "nconflicts ", (u_long)lrp->nconflicts,
-           "nrequests  ", (u_long)lrp->nrequests,
-           "nreleases  ", (u_long)lrp->nreleases,
-           "ndeadlocks ", (u_long)lrp->ndeadlocks);
-       printf("need_dd    %lu\n", (u_long)lrp->need_dd);
-       if (flags & LOCK_DEBUG_CONF) {
-               printf("\nConflict matrix\n");
-
-               for (i = 0; i < lrp->nmodes; i++) {
-                       for (j = 0; j < lrp->nmodes; j++)
-                               printf("%lu\t",
-                                   (u_long)lt->conflicts[i * lrp->nmodes + j]);
-                       printf("\n");
-               }
-       }
-
-       for (i = 0; i < lrp->table_size; i++) {
-               op = SH_TAILQ_FIRST(&lt->hashtab[i], __db_lockobj);
-               if (op != NULL && flags & LOCK_DEBUG_BUCKET)
-                       printf("Bucket %lu:\n", (unsigned long)i);
-               while (op != NULL) {
-                       if (op->type == DB_LOCK_LOCKER &&
-                           flags & LOCK_DEBUG_LOCKERS)
-                               __lock_dump_locker(lt, op);
-                       else if (flags & LOCK_DEBUG_OBJECTS &&
-                           op->type == DB_LOCK_OBJTYPE)
-                               __lock_dump_object(lt, op);
-                       op = SH_TAILQ_NEXT(op, links, __db_lockobj);
-               }
-       }
-
-       if (flags & LOCK_DEBUG_LOCK) {
-               printf("\nLock Free List\n");
-               for (lp = SH_TAILQ_FIRST(&lrp->free_locks, __db_lock);
-                   lp != NULL;
-                   lp = SH_TAILQ_NEXT(lp, links, __db_lock)) {
-                       printf("0x%x: %lu\t%lu\t%lu\t0x%x\n", (u_int)lp,
-                           (u_long)lp->holder, (u_long)lp->mode,
-                           (u_long)lp->status, (u_int)lp->obj);
-               }
-       }
-
-       if (flags & LOCK_DEBUG_LOCK) {
-               printf("\nObject Free List\n");
-               for (op = SH_TAILQ_FIRST(&lrp->free_objs, __db_lockobj);
-                   op != NULL;
-                   op = SH_TAILQ_NEXT(op, links, __db_lockobj))
-                       printf("0x%x\n", (u_int)op);
-       }
-
-       if (flags & LOCK_DEBUG_MEM) {
-               printf("\nMemory Free List\n");
-               __db_shalloc_dump(stdout, lt->mem);
-       }
-}
-
-static void
-__lock_dump_locker(lt, op)
-       DB_LOCKTAB *lt;
-       DB_LOCKOBJ *op;
-{
-       struct __db_lock *lp;
-       u_int32_t locker;
-       void *ptr;
-
-       ptr = SH_DBT_PTR(&op->lockobj);
-       memcpy(&locker, ptr, sizeof(u_int32_t));
-       printf("L %lx", (u_long)locker);
-
-       lp = SH_LIST_FIRST(&op->heldby, __db_lock);
-       if (lp == NULL) {
-               printf("\n");
-               return;
-       }
-       for (; lp != NULL; lp = SH_LIST_NEXT(lp, locker_links, __db_lock))
-               __lock_printlock(lt, lp, 0);
-}
-
-static void
-__lock_dump_object(lt, op)
-       DB_LOCKTAB *lt;
-       DB_LOCKOBJ *op;
-{
-       struct __db_lock *lp;
-       u_int32_t j;
-       char *ptr;
-
-       ptr = SH_DBT_PTR(&op->lockobj);
-       for (j = 0; j < op->lockobj.size; ptr++, j++)
-               printf("%c", (int)*ptr);
-       printf("\n");
-
-       printf("H:");
-       for (lp =
-           SH_TAILQ_FIRST(&op->holders, __db_lock);
-           lp != NULL;
-           lp = SH_TAILQ_NEXT(lp, links, __db_lock))
-               __lock_printlock(lt, lp, 0);
-       lp = SH_TAILQ_FIRST(&op->waiters, __db_lock);
-       if (lp != NULL) {
-               printf("\nW:");
-               for (; lp != NULL; lp = SH_TAILQ_NEXT(lp, links, __db_lock))
-                       __lock_printlock(lt, lp, 0);
-       }
-}
-
-/*
  * __lock_is_locked --
  *
  * PUBLIC: int __lock_is_locked
@@ -1136,7 +565,12 @@ __lock_is_locked(lt, locker, dbt, mode)
        return (0);
 }
 
-static void
+/*
+ * __lock_printlock --
+ *
+ * PUBLIC: void __lock_printlock __P((DB_LOCKTAB *, struct __db_lock *, int));
+ */
+void
 __lock_printlock(lt, lp, ispgno)
        DB_LOCKTAB *lt;
        struct __db_lock *lp;
@@ -1213,39 +647,6 @@ __lock_printlock(lt, lp, ispgno)
                printf("\n");
        }
 }
-#endif
-
-static int
-__lock_count_locks(lrp)
-       DB_LOCKREGION *lrp;
-{
-       struct __db_lock *newl;
-       int count;
-
-       count = 0;
-       for (newl = SH_TAILQ_FIRST(&lrp->free_locks, __db_lock);
-           newl != NULL;
-           newl = SH_TAILQ_NEXT(newl, links, __db_lock))
-               count++;
-
-       return (count);
-}
-
-static int
-__lock_count_objs(lrp)
-       DB_LOCKREGION *lrp;
-{
-       DB_LOCKOBJ *obj;
-       int count;
-
-       count = 0;
-       for (obj = SH_TAILQ_FIRST(&lrp->free_objs, __db_lockobj);
-           obj != NULL;
-           obj = SH_TAILQ_NEXT(obj, links, __db_lockobj))
-               count++;
-
-       return (count);
-}
 
 /*
  * PUBLIC: int __lock_getobj  __P((DB_LOCKTAB *,
@@ -1354,19 +755,7 @@ __lock_remove_waiter(lt, sh_obj, lockp, status)
        lockp->status = status;
 
        /* Wake whoever is waiting on this lock. */
-       (void)__db_mutex_unlock(&lockp->mutex, lt->fd);
-}
-
-static void
-__lock_freeobj(lt, obj)
-       DB_LOCKTAB *lt;
-       DB_LOCKOBJ *obj;
-{
-       HASHREMOVE_EL(lt->hashtab,
-           __db_lockobj, links, obj, lt->region->table_size, __lock_lhash);
-       if (obj->lockobj.size > sizeof(obj->objdata))
-               __db_shalloc_free(lt->mem, SH_DBT_PTR(&obj->lockobj));
-       SH_TAILQ_INSERT_HEAD(&lt->region->free_objs, obj, links, __db_lockobj);
+       (void)__db_mutex_unlock(&lockp->mutex, lt->reginfo.fd);
 }
 
 static void
@@ -1384,17 +773,18 @@ __lock_checklocker(lt, lockp, do_remove)
        if (__lock_getobj(lt, lockp->holder, NULL, DB_LOCK_LOCKER, &sh_locker)
            == 0 && SH_LIST_FIRST(&sh_locker->heldby, __db_lock) == NULL) {
                __lock_freeobj(lt, sh_locker);
-               lt->region->nlockers--;
+                   lt->region->nlockers--;
        }
 }
 
 static void
-__lock_reset_region(lt)
+__lock_freeobj(lt, obj)
        DB_LOCKTAB *lt;
+       DB_LOCKOBJ *obj;
 {
-       lt->conflicts = (u_int8_t *)lt->region + sizeof(DB_LOCKREGION);
-       lt->hashtab =
-           (DB_HASHTAB *)((u_int8_t *)lt->region + lt->region->hash_off);
-       lt->mem = (void *)((u_int8_t *)lt->region + lt->region->mem_off);
-       lt->reg_size = lt->region->hdr.size;
+       HASHREMOVE_EL(lt->hashtab,
+           __db_lockobj, links, obj, lt->region->table_size, __lock_lhash);
+       if (obj->lockobj.size > sizeof(obj->objdata))
+               __db_shalloc_free(lt->mem, SH_DBT_PTR(&obj->lockobj));
+       SH_TAILQ_INSERT_HEAD(&lt->region->free_objs, obj, links, __db_lockobj);
 }
index ff0287f..870aa0d 100644 (file)
@@ -1,14 +1,14 @@
 /*-
  * See the file LICENSE for redistribution information.
  *
- * Copyright (c) 1996, 1997
+ * Copyright (c) 1996, 1997, 1998
  *     Sleepycat Software.  All rights reserved.
  */
 
 #include "config.h"
 
 #ifndef lint
-static const char sccsid[] = "@(#)lock_conflict.c      10.2 (Sleepycat) 6/21/97";
+static const char sccsid[] = "@(#)lock_conflict.c      10.3 (Sleepycat) 4/10/98";
 #endif /* not lint */
 
 #ifndef NO_SYSTEM_INCLUDES
index 93c438c..4de4929 100644 (file)
@@ -1,25 +1,21 @@
 /*-
  * See the file LICENSE for redistribution information.
  *
- * Copyright (c) 1996, 1997
+ * Copyright (c) 1996, 1997, 1998
  *     Sleepycat Software.  All rights reserved.
  */
 
 #include "config.h"
 
 #ifndef lint
-static const char copyright[] =
-"@(#) Copyright (c) 1997\n\
-       Sleepycat Software Inc.  All rights reserved.\n";
-static const char sccsid[] = "@(#)lock_deadlock.c      10.26 (Sleepycat) 11/25/97";
-#endif
+static const char sccsid[] = "@(#)lock_deadlock.c      10.32 (Sleepycat) 4/26/98";
+#endif /* not lint */
 
 #ifndef NO_SYSTEM_INCLUDES
 #include <sys/types.h>
 
 #include <errno.h>
 #include <string.h>
-#include <stdlib.h>
 #endif
 
 #include "db_int.h"
@@ -59,14 +55,14 @@ static int  __dd_build
 static u_int32_t
           *__dd_find __P((u_int32_t *, locker_info *, u_int32_t));
 
-#ifdef DEBUG
+#ifdef DIAGNOSTIC
 static void __dd_debug __P((DB_ENV *, locker_info *, u_int32_t *, u_int32_t));
 #endif
 
 int
 lock_detect(lt, flags, atype)
        DB_LOCKTAB *lt;
-       int flags, atype;
+       u_int32_t flags, atype;
 {
        DB_ENV *dbenv;
        locker_info *idmap;
@@ -96,7 +92,7 @@ lock_detect(lt, flags, atype)
 
        if (nlockers == 0)
                return (0);
-#ifdef DEBUG
+#ifdef DIAGNOSTIC
        if (dbenv->db_verbose != 0)
                __dd_debug(dbenv, idmap, bitmap, nlockers);
 #endif
@@ -202,7 +198,7 @@ __dd_build(dbenv, bmp, nlockers, idmap)
        u_int8_t *pptr;
        locker_info *id_array;
        u_int32_t *bitmap, count, *entryp, i, id, nentries, *tmpmap;
-       int is_first, ret;
+       int is_first;
 
        lt = dbenv->lk_info;
 
@@ -322,8 +318,8 @@ retry:      count = lt->region->nlockers;
                            lp != NULL;
                            is_first = 0,
                            lp = SH_TAILQ_NEXT(lp, links, __db_lock)) {
-                               if ((ret = __lock_getobj(lt, lp->holder,
-                                   NULL, DB_LOCK_LOCKER, &lockerp)) != 0) {
+                               if (__lock_getobj(lt, lp->holder,
+                                   NULL, DB_LOCK_LOCKER, &lockerp) != 0) {
                                        __db_err(dbenv,
                                            "warning unable to find object");
                                        continue;
@@ -357,8 +353,8 @@ retry:      count = lt->region->nlockers;
        for (id = 0; id < count; id++) {
                if (!id_array[id].valid)
                        continue;
-               if ((ret = __lock_getobj(lt,
-                   id_array[id].id, NULL, DB_LOCK_LOCKER, &lockerp)) != 0) {
+               if (__lock_getobj(lt,
+                   id_array[id].id, NULL, DB_LOCK_LOCKER, &lockerp) != 0) {
                        __db_err(dbenv,
                            "No locks for locker %lu", (u_long)id_array[id].id);
                        continue;
@@ -448,7 +444,7 @@ __dd_abort(dbenv, info)
        SH_LIST_REMOVE(lockp, locker_links, __db_lock);
        sh_obj = (DB_LOCKOBJ *)((u_int8_t *)lockp + lockp->obj);
        SH_TAILQ_REMOVE(&sh_obj->waiters, lockp, links, __db_lock);
-        (void)__db_mutex_unlock(&lockp->mutex, lt->fd);
+        (void)__db_mutex_unlock(&lockp->mutex, lt->reginfo.fd);
 
        ret = 0;
 
@@ -456,7 +452,7 @@ out:        UNLOCK_LOCKREGION(lt);
        return (ret);
 }
 
-#ifdef DEBUG
+#ifdef DIAGNOSTIC
 static void
 __dd_debug(dbenv, idmap, bitmap, nlockers)
        DB_ENV *dbenv;
diff --git a/db2/lock/lock_region.c b/db2/lock/lock_region.c
new file mode 100644 (file)
index 0000000..b597560
--- /dev/null
@@ -0,0 +1,726 @@
+/*-
+ * See the file LICENSE for redistribution information.
+ *
+ * Copyright (c) 1996, 1997, 1998
+ *     Sleepycat Software.  All rights reserved.
+ */
+
+#include "config.h"
+
+#ifndef lint
+static const char sccsid[] = "@(#)lock_region.c        10.15 (Sleepycat) 6/2/98";
+#endif /* not lint */
+
+#ifndef NO_SYSTEM_INCLUDES
+#include <sys/types.h>
+
+#include <ctype.h>
+#include <errno.h>
+#include <string.h>
+#endif
+
+#include "db_int.h"
+#include "shqueue.h"
+#include "db_shash.h"
+#include "lock.h"
+#include "common_ext.h"
+
+static u_int32_t __lock_count_locks __P((DB_LOCKREGION *));
+static u_int32_t __lock_count_objs __P((DB_LOCKREGION *));
+static void     __lock_dump_locker __P((DB_LOCKTAB *, DB_LOCKOBJ *, FILE *));
+static void     __lock_dump_object __P((DB_LOCKTAB *, DB_LOCKOBJ *, FILE *));
+static const char *__lock_dump_status __P((db_status_t));
+static void     __lock_reset_region __P((DB_LOCKTAB *));
+static int      __lock_tabinit __P((DB_ENV *, DB_LOCKREGION *));
+
+int
+lock_open(path, flags, mode, dbenv, ltp)
+       const char *path;
+       u_int32_t flags;
+       int mode;
+       DB_ENV *dbenv;
+       DB_LOCKTAB **ltp;
+{
+       DB_LOCKTAB *lt;
+       u_int32_t lock_modes, maxlocks, regflags;
+       int ret;
+
+       /* Validate arguments. */
+#ifdef HAVE_SPINLOCKS
+#define        OKFLAGS (DB_CREATE | DB_THREAD)
+#else
+#define        OKFLAGS (DB_CREATE)
+#endif
+       if ((ret = __db_fchk(dbenv, "lock_open", flags, OKFLAGS)) != 0)
+               return (ret);
+
+       /* Create the lock table structure. */
+       if ((lt = (DB_LOCKTAB *)__db_calloc(1, sizeof(DB_LOCKTAB))) == NULL) {
+               __db_err(dbenv, "%s", strerror(ENOMEM));
+               return (ENOMEM);
+       }
+       lt->dbenv = dbenv;
+
+       /* Grab the values that we need to compute the region size. */
+       lock_modes = DB_LOCK_RW_N;
+       maxlocks = DB_LOCK_DEFAULT_N;
+       regflags = REGION_SIZEDEF;
+       if (dbenv != NULL) {
+               if (dbenv->lk_modes != 0) {
+                       lock_modes = dbenv->lk_modes;
+                       regflags = 0;
+               }
+               if (dbenv->lk_max != 0) {
+                       maxlocks = dbenv->lk_max;
+                       regflags = 0;
+               }
+       }
+
+       /* Join/create the lock region. */
+       lt->reginfo.dbenv = dbenv;
+       lt->reginfo.appname = DB_APP_NONE;
+       if (path == NULL)
+               lt->reginfo.path = NULL;
+       else
+               if ((lt->reginfo.path = (char *)__db_strdup(path)) == NULL)
+                       goto err;
+       lt->reginfo.file = DB_DEFAULT_LOCK_FILE;
+       lt->reginfo.mode = mode;
+       lt->reginfo.size =
+           LOCK_REGION_SIZE(lock_modes, maxlocks, __db_tablesize(maxlocks));
+       lt->reginfo.dbflags = flags;
+       lt->reginfo.addr = NULL;
+       lt->reginfo.fd = -1;
+       lt->reginfo.flags = regflags;
+
+       if ((ret = __db_rattach(&lt->reginfo)) != 0)
+               goto err;
+
+       /* Now set up the pointer to the region. */
+       lt->region = lt->reginfo.addr;
+
+       /* Initialize the region if we created it. */
+       if (F_ISSET(&lt->reginfo, REGION_CREATED)) {
+               lt->region->maxlocks = maxlocks;
+               lt->region->nmodes = lock_modes;
+               if ((ret = __lock_tabinit(dbenv, lt->region)) != 0)
+                       goto err;
+       } else {
+               /* Check for an unexpected region. */
+               if (lt->region->magic != DB_LOCKMAGIC) {
+                       __db_err(dbenv,
+                           "lock_open: %s: bad magic number", path);
+                       ret = EINVAL;
+                       goto err;
+               }
+       }
+
+       /* Check for automatic deadlock detection. */
+       if (dbenv != NULL && dbenv->lk_detect != DB_LOCK_NORUN) {
+               if (lt->region->detect != DB_LOCK_NORUN &&
+                   dbenv->lk_detect != DB_LOCK_DEFAULT &&
+                   lt->region->detect != dbenv->lk_detect) {
+                       __db_err(dbenv,
+                   "lock_open: incompatible deadlock detector mode");
+                       ret = EINVAL;
+                       goto err;
+               }
+               if (lt->region->detect == DB_LOCK_NORUN)
+                       lt->region->detect = dbenv->lk_detect;
+       }
+
+       /* Set up remaining pointers into region. */
+       lt->conflicts = (u_int8_t *)lt->region + sizeof(DB_LOCKREGION);
+       lt->hashtab =
+           (DB_HASHTAB *)((u_int8_t *)lt->region + lt->region->hash_off);
+       lt->mem = (void *)((u_int8_t *)lt->region + lt->region->mem_off);
+
+       UNLOCK_LOCKREGION(lt);
+       *ltp = lt;
+       return (0);
+
+err:   if (lt->reginfo.addr != NULL) {
+               UNLOCK_LOCKREGION(lt);
+               (void)__db_rdetach(&lt->reginfo);
+               if (F_ISSET(&lt->reginfo, REGION_CREATED))
+                       (void)lock_unlink(path, 1, dbenv);
+       }
+
+       if (lt->reginfo.path != NULL)
+               FREES(lt->reginfo.path);
+       FREE(lt, sizeof(*lt));
+       return (ret);
+}
+
+/*
+ * __lock_tabinit --
+ *     Initialize the lock region.
+ */
+static int
+__lock_tabinit(dbenv, lrp)
+       DB_ENV *dbenv;
+       DB_LOCKREGION *lrp;
+{
+       struct __db_lock *lp;
+       struct lock_header *tq_head;
+       struct obj_header *obj_head;
+       DB_LOCKOBJ *op;
+       u_int32_t i, nelements;
+       const u_int8_t *conflicts;
+       u_int8_t *curaddr;
+
+       conflicts = dbenv == NULL || dbenv->lk_conflicts == NULL ?
+           db_rw_conflicts : dbenv->lk_conflicts;
+
+       lrp->table_size = __db_tablesize(lrp->maxlocks);
+       lrp->magic = DB_LOCKMAGIC;
+       lrp->version = DB_LOCKVERSION;
+       lrp->id = 0;
+       /*
+        * These fields (lrp->maxlocks, lrp->nmodes) are initialized
+        * in the caller, since we had to grab those values to size
+        * the region.
+        */
+       lrp->need_dd = 0;
+       lrp->detect = DB_LOCK_NORUN;
+       lrp->numobjs = lrp->maxlocks;
+       lrp->nlockers = 0;
+       lrp->mem_bytes = ALIGN(STRING_SIZE(lrp->maxlocks), sizeof(size_t));
+       lrp->increment = lrp->hdr.size / 2;
+       lrp->nconflicts = 0;
+       lrp->nrequests = 0;
+       lrp->nreleases = 0;
+       lrp->ndeadlocks = 0;
+
+       /*
+        * As we write the region, we've got to maintain the alignment
+        * for the structures that follow each chunk.  This information
+        * ends up being encapsulated both in here as well as in the
+        * lock.h file for the XXX_SIZE macros.
+        */
+       /* Initialize conflict matrix. */
+       curaddr = (u_int8_t *)lrp + sizeof(DB_LOCKREGION);
+       memcpy(curaddr, conflicts, lrp->nmodes * lrp->nmodes);
+       curaddr += lrp->nmodes * lrp->nmodes;
+
+       /*
+        * Initialize hash table.
+        */
+       curaddr = (u_int8_t *)ALIGNP(curaddr, LOCK_HASH_ALIGN);
+       lrp->hash_off = curaddr - (u_int8_t *)lrp;
+       nelements = lrp->table_size;
+       __db_hashinit(curaddr, nelements);
+       curaddr += nelements * sizeof(DB_HASHTAB);
+
+       /*
+        * Initialize locks onto a free list. Since locks contains mutexes,
+        * we need to make sure that each lock is aligned on a MUTEX_ALIGNMENT
+        * boundary.
+        */
+       curaddr = (u_int8_t *)ALIGNP(curaddr, MUTEX_ALIGNMENT);
+       tq_head = &lrp->free_locks;
+       SH_TAILQ_INIT(tq_head);
+
+       for (i = 0; i++ < lrp->maxlocks;
+           curaddr += ALIGN(sizeof(struct __db_lock), MUTEX_ALIGNMENT)) {
+               lp = (struct __db_lock *)curaddr;
+               lp->status = DB_LSTAT_FREE;
+               SH_TAILQ_INSERT_HEAD(tq_head, lp, links, __db_lock);
+       }
+
+       /* Initialize objects onto a free list.  */
+       obj_head = &lrp->free_objs;
+       SH_TAILQ_INIT(obj_head);
+
+       for (i = 0; i++ < lrp->maxlocks; curaddr += sizeof(DB_LOCKOBJ)) {
+               op = (DB_LOCKOBJ *)curaddr;
+               SH_TAILQ_INSERT_HEAD(obj_head, op, links, __db_lockobj);
+       }
+
+       /*
+        * Initialize the string space; as for all shared memory allocation
+        * regions, this requires size_t alignment, since we store the
+        * lengths of malloc'd areas in the area.
+        */
+       curaddr = (u_int8_t *)ALIGNP(curaddr, sizeof(size_t));
+       lrp->mem_off = curaddr - (u_int8_t *)lrp;
+       __db_shalloc_init(curaddr, lrp->mem_bytes);
+       return (0);
+}
+
+int
+lock_close(lt)
+       DB_LOCKTAB *lt;
+{
+       int ret;
+
+       if ((ret = __db_rdetach(&lt->reginfo)) != 0)
+               return (ret);
+
+       if (lt->reginfo.path != NULL)
+               FREES(lt->reginfo.path);
+       FREE(lt, sizeof(*lt));
+
+       return (0);
+}
+
+int
+lock_unlink(path, force, dbenv)
+       const char *path;
+       int force;
+       DB_ENV *dbenv;
+{
+       REGINFO reginfo;
+       int ret;
+
+       memset(&reginfo, 0, sizeof(reginfo));
+       reginfo.dbenv = dbenv;
+       reginfo.appname = DB_APP_NONE;
+       if (path != NULL && (reginfo.path = (char *)__db_strdup(path)) == NULL)
+               return (ENOMEM);
+       reginfo.file = DB_DEFAULT_LOCK_FILE;
+       ret = __db_runlink(&reginfo, force);
+       if (reginfo.path != NULL)
+               FREES(reginfo.path);
+       return (ret);
+}
+
+/*
+ * __lock_validate_region --
+ *     Called at every interface to verify if the region has changed size,
+ *     and if so, to remap the region in and reset the process' pointers.
+ *
+ * PUBLIC: int __lock_validate_region __P((DB_LOCKTAB *));
+ */
+int
+__lock_validate_region(lt)
+       DB_LOCKTAB *lt;
+{
+       int ret;
+
+       if (lt->reginfo.size == lt->region->hdr.size)
+               return (0);
+
+       /* Detach/reattach the region. */
+       if ((ret = __db_rreattach(&lt->reginfo, lt->region->hdr.size)) != 0)
+               return (ret);
+
+       /* Reset region information. */
+       lt->region = lt->reginfo.addr;
+       __lock_reset_region(lt);
+
+       return (0);
+}
+
+/*
+ * __lock_grow_region --
+ *     We have run out of space; time to grow the region.
+ *
+ * PUBLIC: int __lock_grow_region __P((DB_LOCKTAB *, int, size_t));
+ */
+int
+__lock_grow_region(lt, which, howmuch)
+       DB_LOCKTAB *lt;
+       int which;
+       size_t howmuch;
+{
+       struct __db_lock *newl;
+       struct lock_header *lock_head;
+       struct obj_header *obj_head;
+       DB_LOCKOBJ *op;
+       DB_LOCKREGION *lrp;
+       float lock_ratio, obj_ratio;
+       size_t incr, oldsize, used, usedmem;
+       u_int32_t i, newlocks, newmem, newobjs, usedlocks, usedobjs;
+       u_int8_t *curaddr;
+       int ret;
+
+       lrp = lt->region;
+       oldsize = lrp->hdr.size;
+       incr = lrp->increment;
+
+       /* Figure out how much of each sort of space we have. */
+       usedmem = lrp->mem_bytes - __db_shalloc_count(lt->mem);
+       usedobjs = lrp->numobjs - __lock_count_objs(lrp);
+       usedlocks = lrp->maxlocks - __lock_count_locks(lrp);
+
+       /*
+        * Figure out what fraction of the used space belongs to each
+        * different type of "thing" in the region.  Then partition the
+        * new space up according to this ratio.
+        */
+       used = usedmem +
+           usedlocks * ALIGN(sizeof(struct __db_lock), MUTEX_ALIGNMENT) +
+           usedobjs * sizeof(DB_LOCKOBJ);
+
+       lock_ratio = usedlocks *
+           ALIGN(sizeof(struct __db_lock), MUTEX_ALIGNMENT) / (float)used;
+       obj_ratio = usedobjs * sizeof(DB_LOCKOBJ) / (float)used;
+
+       newlocks = (u_int32_t)(lock_ratio *
+           incr / ALIGN(sizeof(struct __db_lock), MUTEX_ALIGNMENT));
+       newobjs = (u_int32_t)(obj_ratio * incr / sizeof(DB_LOCKOBJ));
+       newmem = incr -
+           (newobjs * sizeof(DB_LOCKOBJ) +
+           newlocks * ALIGN(sizeof(struct __db_lock), MUTEX_ALIGNMENT));
+
+       /*
+        * Make sure we allocate enough memory for the object being
+        * requested.
+        */
+       switch (which) {
+       case DB_LOCK_LOCK:
+               if (newlocks == 0) {
+                       newlocks = 10;
+                       incr += newlocks * sizeof(struct __db_lock);
+               }
+               break;
+       case DB_LOCK_OBJ:
+               if (newobjs == 0) {
+                       newobjs = 10;
+                       incr += newobjs * sizeof(DB_LOCKOBJ);
+               }
+               break;
+       case DB_LOCK_MEM:
+               if (newmem < howmuch * 2) {
+                       incr += howmuch * 2 - newmem;
+                       newmem = howmuch * 2;
+               }
+               break;
+       }
+
+       newmem += ALIGN(incr, sizeof(size_t)) - incr;
+       incr = ALIGN(incr, sizeof(size_t));
+
+       /*
+        * Since we are going to be allocating locks at the beginning of the
+        * new chunk, we need to make sure that the chunk is MUTEX_ALIGNMENT
+        * aligned.  We did not guarantee this when we created the region, so
+        * we may need to pad the old region by extra bytes to ensure this
+        * alignment.
+        */
+       incr += ALIGN(oldsize, MUTEX_ALIGNMENT) - oldsize;
+
+       __db_err(lt->dbenv,
+           "Growing lock region: %lu locks %lu objs %lu bytes",
+           (u_long)newlocks, (u_long)newobjs, (u_long)newmem);
+
+       if ((ret = __db_rgrow(&lt->reginfo, oldsize + incr)) != 0)
+               return (ret);
+       lt->region = lt->reginfo.addr;
+       __lock_reset_region(lt);
+
+       /* Update region parameters. */
+       lrp = lt->region;
+       lrp->increment = incr << 1;
+       lrp->maxlocks += newlocks;
+       lrp->numobjs += newobjs;
+       lrp->mem_bytes += newmem;
+
+       curaddr = (u_int8_t *)lrp + oldsize;
+       curaddr = (u_int8_t *)ALIGNP(curaddr, MUTEX_ALIGNMENT);
+
+       /* Put new locks onto the free list. */
+       lock_head = &lrp->free_locks;
+       for (i = 0; i++ < newlocks;
+           curaddr += ALIGN(sizeof(struct __db_lock), MUTEX_ALIGNMENT)) {
+               newl = (struct __db_lock *)curaddr;
+               SH_TAILQ_INSERT_HEAD(lock_head, newl, links, __db_lock);
+       }
+
+       /* Put new objects onto the free list.  */
+       obj_head = &lrp->free_objs;
+       for (i = 0; i++ < newobjs; curaddr += sizeof(DB_LOCKOBJ)) {
+               op = (DB_LOCKOBJ *)curaddr;
+               SH_TAILQ_INSERT_HEAD(obj_head, op, links, __db_lockobj);
+       }
+
+       *((size_t *)curaddr) = newmem - sizeof(size_t);
+       curaddr += sizeof(size_t);
+       __db_shalloc_free(lt->mem, curaddr);
+
+       return (0);
+}
+
+static void
+__lock_reset_region(lt)
+       DB_LOCKTAB *lt;
+{
+       lt->conflicts = (u_int8_t *)lt->region + sizeof(DB_LOCKREGION);
+       lt->hashtab =
+           (DB_HASHTAB *)((u_int8_t *)lt->region + lt->region->hash_off);
+       lt->mem = (void *)((u_int8_t *)lt->region + lt->region->mem_off);
+}
+
+/*
+ * lock_stat --
+ *     Return LOCK statistics.
+ */
+int
+lock_stat(lt, gspp, db_malloc)
+       DB_LOCKTAB *lt;
+       DB_LOCK_STAT **gspp;
+       void *(*db_malloc) __P((size_t));
+{
+       DB_LOCKREGION *rp;
+
+       *gspp = NULL;
+
+       if ((*gspp = db_malloc == NULL ?
+           (DB_LOCK_STAT *)__db_malloc(sizeof(**gspp)) :
+           (DB_LOCK_STAT *)db_malloc(sizeof(**gspp))) == NULL)
+               return (ENOMEM);
+
+       /* Copy out the global statistics. */
+       LOCK_LOCKREGION(lt);
+
+       rp = lt->region;
+       (*gspp)->st_magic = rp->magic;
+       (*gspp)->st_version = rp->version;
+       (*gspp)->st_maxlocks = rp->maxlocks;
+       (*gspp)->st_nmodes = rp->nmodes;
+       (*gspp)->st_numobjs = rp->numobjs;
+       (*gspp)->st_nlockers = rp->nlockers;
+       (*gspp)->st_nconflicts = rp->nconflicts;
+       (*gspp)->st_nrequests = rp->nrequests;
+       (*gspp)->st_nreleases = rp->nreleases;
+       (*gspp)->st_ndeadlocks = rp->ndeadlocks;
+       (*gspp)->st_region_nowait = rp->hdr.lock.mutex_set_nowait;
+       (*gspp)->st_region_wait = rp->hdr.lock.mutex_set_wait;
+       (*gspp)->st_refcnt = rp->hdr.refcnt;
+       (*gspp)->st_regsize = rp->hdr.size;
+
+       UNLOCK_LOCKREGION(lt);
+
+       return (0);
+}
+
+static u_int32_t
+__lock_count_locks(lrp)
+       DB_LOCKREGION *lrp;
+{
+       struct __db_lock *newl;
+       u_int32_t count;
+
+       count = 0;
+       for (newl = SH_TAILQ_FIRST(&lrp->free_locks, __db_lock);
+           newl != NULL;
+           newl = SH_TAILQ_NEXT(newl, links, __db_lock))
+               count++;
+
+       return (count);
+}
+
+static u_int32_t
+__lock_count_objs(lrp)
+       DB_LOCKREGION *lrp;
+{
+       DB_LOCKOBJ *obj;
+       u_int32_t count;
+
+       count = 0;
+       for (obj = SH_TAILQ_FIRST(&lrp->free_objs, __db_lockobj);
+           obj != NULL;
+           obj = SH_TAILQ_NEXT(obj, links, __db_lockobj))
+               count++;
+
+       return (count);
+}
+
+#define        LOCK_DUMP_CONF          0x001           /* Conflict matrix. */
+#define        LOCK_DUMP_FREE          0x002           /* Display lock free list. */
+#define        LOCK_DUMP_LOCKERS       0x004           /* Display lockers. */
+#define        LOCK_DUMP_MEM           0x008           /* Display region memory. */
+#define        LOCK_DUMP_OBJECTS       0x010           /* Display objects. */
+#define        LOCK_DUMP_ALL           0x01f           /* Display all. */
+
+/*
+ * __lock_dump_region --
+ *
+ * PUBLIC: void __lock_dump_region __P((DB_LOCKTAB *, char *, FILE *));
+ */
+void
+__lock_dump_region(lt, area, fp)
+       DB_LOCKTAB *lt;
+       char *area;
+       FILE *fp;
+{
+       struct __db_lock *lp;
+       DB_LOCKOBJ *op;
+       DB_LOCKREGION *lrp;
+       u_int32_t flags, i, j;
+       int label;
+
+       /* Make it easy to call from the debugger. */
+       if (fp == NULL)
+               fp = stderr;
+
+       for (flags = 0; *area != '\0'; ++area)
+               switch (*area) {
+               case 'A':
+                       LF_SET(LOCK_DUMP_ALL);
+                       break;
+               case 'c':
+                       LF_SET(LOCK_DUMP_CONF);
+                       break;
+               case 'f':
+                       LF_SET(LOCK_DUMP_FREE);
+                       break;
+               case 'l':
+                       LF_SET(LOCK_DUMP_LOCKERS);
+                       break;
+               case 'm':
+                       LF_SET(LOCK_DUMP_MEM);
+                       break;
+               case 'o':
+                       LF_SET(LOCK_DUMP_OBJECTS);
+                       break;
+               }
+
+       lrp = lt->region;
+
+       fprintf(fp, "%s\nLock region parameters\n", DB_LINE);
+       fprintf(fp, "%s: %lu, %s: %lu, %s: %lu, %s: %lu\n%s: %lu, %s: %lu\n",
+           "table size", (u_long)lrp->table_size,
+           "hash_off", (u_long)lrp->hash_off,
+           "increment", (u_long)lrp->increment,
+           "mem_off", (u_long)lrp->mem_off,
+           "mem_bytes", (u_long)lrp->mem_bytes,
+           "need_dd", (u_long)lrp->need_dd);
+
+       if (LF_ISSET(LOCK_DUMP_CONF)) {
+               fprintf(fp, "\n%s\nConflict matrix\n", DB_LINE);
+               for (i = 0; i < lrp->nmodes; i++) {
+                       for (j = 0; j < lrp->nmodes; j++)
+                               fprintf(fp, "%lu\t",
+                                   (u_long)lt->conflicts[i * lrp->nmodes + j]);
+                       fprintf(fp, "\n");
+               }
+       }
+
+       if (LF_ISSET(LOCK_DUMP_LOCKERS | LOCK_DUMP_OBJECTS)) {
+               fprintf(fp, "%s\nLock hash buckets\n", DB_LINE);
+               for (i = 0; i < lrp->table_size; i++) {
+                       label = 1;
+                       for (op = SH_TAILQ_FIRST(&lt->hashtab[i], __db_lockobj);
+                           op != NULL;
+                           op = SH_TAILQ_NEXT(op, links, __db_lockobj)) {
+                               if (LF_ISSET(LOCK_DUMP_LOCKERS) &&
+                                   op->type == DB_LOCK_LOCKER) {
+                                       if (label) {
+                                               fprintf(fp,
+                                                   "Bucket %lu:\n", (u_long)i);
+                                               label = 0;
+                                       }
+                                       __lock_dump_locker(lt, op, fp);
+                               }
+                               if (LF_ISSET(LOCK_DUMP_OBJECTS) &&
+                                   op->type == DB_LOCK_OBJTYPE) {
+                                       if (label) {
+                                               fprintf(fp,
+                                                   "Bucket %lu:\n", (u_long)i);
+                                               label = 0;
+                                       }
+                                       __lock_dump_object(lt, op, fp);
+                               }
+                       }
+               }
+       }
+
+       if (LF_ISSET(LOCK_DUMP_FREE)) {
+               fprintf(fp, "%s\nLock free list\n", DB_LINE);
+               for (lp = SH_TAILQ_FIRST(&lrp->free_locks, __db_lock);
+                   lp != NULL;
+                   lp = SH_TAILQ_NEXT(lp, links, __db_lock))
+                       fprintf(fp, "0x%x: %lu\t%lu\t%s\t0x%x\n", (u_int)lp,
+                           (u_long)lp->holder, (u_long)lp->mode,
+                           __lock_dump_status(lp->status), (u_int)lp->obj);
+
+               fprintf(fp, "%s\nObject free list\n", DB_LINE);
+               for (op = SH_TAILQ_FIRST(&lrp->free_objs, __db_lockobj);
+                   op != NULL;
+                   op = SH_TAILQ_NEXT(op, links, __db_lockobj))
+                       fprintf(fp, "0x%x\n", (u_int)op);
+       }
+
+       if (LF_ISSET(LOCK_DUMP_MEM))
+               __db_shalloc_dump(lt->mem, fp);
+}
+
+static void
+__lock_dump_locker(lt, op, fp)
+       DB_LOCKTAB *lt;
+       DB_LOCKOBJ *op;
+       FILE *fp;
+{
+       struct __db_lock *lp;
+       u_int32_t locker;
+       void *ptr;
+
+       ptr = SH_DBT_PTR(&op->lockobj);
+       memcpy(&locker, ptr, sizeof(u_int32_t));
+       fprintf(fp, "L %lx", (u_long)locker);
+
+       lp = SH_LIST_FIRST(&op->heldby, __db_lock);
+       if (lp == NULL) {
+               fprintf(fp, "\n");
+               return;
+       }
+       for (; lp != NULL; lp = SH_LIST_NEXT(lp, locker_links, __db_lock))
+               __lock_printlock(lt, lp, 0);
+}
+
+static void
+__lock_dump_object(lt, op, fp)
+       DB_LOCKTAB *lt;
+       DB_LOCKOBJ *op;
+       FILE *fp;
+{
+       struct __db_lock *lp;
+       u_int32_t j;
+       u_int8_t *ptr;
+       u_int ch;
+
+       ptr = SH_DBT_PTR(&op->lockobj);
+       for (j = 0; j < op->lockobj.size; ptr++, j++) {
+               ch = *ptr;
+               fprintf(fp, isprint(ch) ? "%c" : "\\%o", ch);
+       }
+       fprintf(fp, "\n");
+
+       fprintf(fp, "H:");
+       for (lp =
+           SH_TAILQ_FIRST(&op->holders, __db_lock);
+           lp != NULL;
+           lp = SH_TAILQ_NEXT(lp, links, __db_lock))
+               __lock_printlock(lt, lp, 0);
+       lp = SH_TAILQ_FIRST(&op->waiters, __db_lock);
+       if (lp != NULL) {
+               fprintf(fp, "\nW:");
+               for (; lp != NULL; lp = SH_TAILQ_NEXT(lp, links, __db_lock))
+                       __lock_printlock(lt, lp, 0);
+       }
+}
+
+static const char *
+__lock_dump_status(status)
+       db_status_t status;
+{
+       switch (status) {
+       case DB_LSTAT_ABORTED:
+               return ("aborted");
+       case DB_LSTAT_ERR:
+               return ("err");
+       case DB_LSTAT_FREE:
+               return ("free");
+       case DB_LSTAT_HELD:
+               return ("held");
+       case DB_LSTAT_NOGRANT:
+               return ("nogrant");
+       case DB_LSTAT_PENDING:
+               return ("pending");
+       case DB_LSTAT_WAITING:
+               return ("waiting");
+       }
+       return ("unknown status");
+}
index 6c1e30f..7274a50 100644 (file)
@@ -1,25 +1,20 @@
 /*-
  * See the file LICENSE for redistribution information.
  *
- * Copyright (c) 1996, 1997
+ * Copyright (c) 1996, 1997, 1998
  *     Sleepycat Software.  All rights reserved.
  */
 
 #include "config.h"
 
 #ifndef lint
-static const char sccsid[] = "@(#)lock_util.c  10.5 (Sleepycat) 1/8/98";
+static const char sccsid[] = "@(#)lock_util.c  10.9 (Sleepycat) 4/26/98";
 #endif /* not lint */
 
 #ifndef NO_SYSTEM_INCLUDES
 #include <sys/types.h>
 
-#include <fcntl.h>
-#include <stddef.h>
-#include <stdio.h>
-#include <stdlib.h>
 #include <string.h>
-#include <unistd.h>
 #endif
 
 #include "db_int.h"
@@ -30,11 +25,13 @@ static const char sccsid[] = "@(#)lock_util.c       10.5 (Sleepycat) 1/8/98";
 #include "lock.h"
 
 /*
- * This function is used to compare a DBT that is about to be entered
- * into a hash table with an object already in the hash table.  Note
- * that it just returns true on equal and 0 on not-equal.  Therefore this
- * cannot be used as a sort function; its purpose is to be used as a
- * hash comparison function.
+ * __lock_cmp --
+ *     This function is used to compare a DBT that is about to be entered
+ *     into a hash table with an object already in the hash table.  Note
+ *     that it just returns true on equal and 0 on not-equal.  Therefore
+ *     this function cannot be used as a sort function; its purpose is to
+ *     be used as a hash comparison function.
+ *
  * PUBLIC: int __lock_cmp __P((const DBT *, DB_LOCKOBJ *));
  */
 int
@@ -46,6 +43,7 @@ __lock_cmp(dbt, lock_obj)
 
        if (lock_obj->type != DB_LOCK_OBJTYPE)
                return (0);
+
        obj_data = SH_DBT_PTR(&lock_obj->lockobj);
        return (dbt->size == lock_obj->lockobj.size &&
                memcmp(dbt->data, obj_data, dbt->size) == 0);
@@ -69,35 +67,86 @@ __lock_locker_cmp(locker, lock_obj)
 }
 
 /*
- * PUBLIC: int __lock_ohash __P((const DBT *));
+ * The next two functions are the hash functions used to store objects in the
+ * lock hash table.  They are hashing the same items, but one (__lock_ohash)
+ * takes a DBT (used for hashing a parameter passed from the user) and the
+ * other (__lock_lhash) takes a DB_LOCKOBJ (used for hashing something that is
+ * already in the lock manager).  In both cases, we have a special check to
+ * fast path the case where we think we are doing a hash on a DB page/fileid
+ * pair.  If the size is right, then we do the fast hash.
+ *
+ * We know that DB uses struct __db_ilocks for its lock objects.  The first
+ * four bytes are the 4-byte page number and the next DB_FILE_ID_LEN bytes
+ * are a unique file id, where the first 4 bytes on UNIX systems are the file
+ * inode number, and the first 4 bytes on Windows systems are the FileIndexLow
+ * bytes.  So, we use the XOR of the page number and the first four bytes of
+ * the file id to produce a 32-bit hash value.
+ *
+ * We have no particular reason to believe that this algorithm will produce
+ * a good hash, but we want a fast hash more than we want a good one, when
+ * we're coming through this code path.
  */
-int
-__lock_ohash(dbt)
-       const DBT *dbt;
-{
-       return (__ham_func5(dbt->data, dbt->size));
+#define FAST_HASH(P) {                 \
+       u_int32_t __h;                  \
+       u_int8_t *__cp, *__hp;          \
+       __hp = (u_int8_t *)&__h;        \
+       __cp = (u_int8_t *)(P);         \
+       __hp[0] = __cp[0] ^ __cp[4];    \
+       __hp[1] = __cp[1] ^ __cp[5];    \
+       __hp[2] = __cp[2] ^ __cp[6];    \
+       __hp[3] = __cp[3] ^ __cp[7];    \
+       return (__h);                   \
 }
 
 /*
- * PUBLIC: u_int32_t __lock_locker_hash __P((u_int32_t));
+ * __lock_ohash --
+ *
+ * PUBLIC: u_int32_t __lock_ohash __P((const DBT *));
  */
 u_int32_t
-__lock_locker_hash(locker)
-       u_int32_t locker;
+__lock_ohash(dbt)
+       const DBT *dbt;
 {
-       return (__ham_func5(&locker, sizeof(locker)));
+       if (dbt->size == sizeof(struct __db_ilock))
+               FAST_HASH(dbt->data);
+
+       return (__ham_func5(dbt->data, dbt->size));
 }
 
 /*
+ * __lock_lhash --
+ *
  * PUBLIC: u_int32_t __lock_lhash __P((DB_LOCKOBJ *));
  */
 u_int32_t
 __lock_lhash(lock_obj)
        DB_LOCKOBJ *lock_obj;
 {
+       u_int32_t tmp;
        void *obj_data;
 
        obj_data = SH_DBT_PTR(&lock_obj->lockobj);
+       if (lock_obj->type == DB_LOCK_LOCKER) {
+               memcpy(&tmp, obj_data, sizeof(u_int32_t));
+               return (tmp);
+       }
+
+       if (lock_obj->lockobj.size == sizeof(struct __db_ilock))
+               FAST_HASH(obj_data);
+
        return (__ham_func5(obj_data, lock_obj->lockobj.size));
 }
 
+/*
+ * __lock_locker_hash --
+ *     Hash function for entering lockers into the hash table.  Since these
+ *     are simply 32-bit unsigned integers, just return the locker value.
+ *
+ * PUBLIC: u_int32_t __lock_locker_hash __P((u_int32_t));
+ */
+u_int32_t
+__lock_locker_hash(locker)
+       u_int32_t locker;
+{
+       return (locker);
+}
index 8013d42..d642c9f 100644 (file)
@@ -1,21 +1,19 @@
 /*-
  * See the file LICENSE for redistribution information.
  *
- * Copyright (c) 1996, 1997
+ * Copyright (c) 1996, 1997, 1998
  *     Sleepycat Software.  All rights reserved.
  */
 #include "config.h"
 
 #ifndef lint
-static const char sccsid[] = "@(#)log.c        10.39 (Sleepycat) 1/17/98";
+static const char sccsid[] = "@(#)log.c        10.54 (Sleepycat) 5/31/98";
 #endif /* not lint */
 
 #ifndef NO_SYSTEM_INCLUDES
 #include <sys/types.h>
-#include <sys/stat.h>
 
 #include <errno.h>
-#include <fcntl.h>
 #include <stdlib.h>
 #include <string.h>
 #include <unistd.h>
@@ -23,7 +21,6 @@ static const char sccsid[] = "@(#)log.c       10.39 (Sleepycat) 1/17/98";
 
 #include "db_int.h"
 #include "shqueue.h"
-#include "db_shash.h"
 #include "log.h"
 #include "db_dispatch.h"
 #include "txn_auto.h"
@@ -38,15 +35,14 @@ static int __log_recover __P((DB_LOG *));
 int
 log_open(path, flags, mode, dbenv, lpp)
        const char *path;
-       int flags;
+       u_int32_t flags;
        int mode;
        DB_ENV *dbenv;
        DB_LOG **lpp;
 {
        DB_LOG *dblp;
        LOG *lp;
-       size_t len;
-       int fd, newregion, ret, retry_cnt;
+       int ret;
 
        /* Validate arguments. */
 #ifdef HAVE_SPINLOCKS
@@ -57,22 +53,13 @@ log_open(path, flags, mode, dbenv, lpp)
        if ((ret = __db_fchk(dbenv, "log_open", flags, OKFLAGS)) != 0)
                return (ret);
 
-       /*
-        * We store 4-byte offsets into the file, so the maximum file
-        * size can't be larger than that.
-        */
-       if (dbenv != NULL && dbenv->lg_max > UINT32_T_MAX) {
-               __db_err(dbenv, "log_open: maximum file size too large");
-               return (EINVAL);
-       }
-
        /* Create and initialize the DB_LOG structure. */
        if ((dblp = (DB_LOG *)__db_calloc(1, sizeof(DB_LOG))) == NULL)
                return (ENOMEM);
 
        if (path != NULL && (dblp->dir = __db_strdup(path)) == NULL) {
-               __db_free(dblp);
-               return (ENOMEM);
+               ret = ENOMEM;
+               goto err;
        }
 
        dblp->dbenv = dbenv;
@@ -85,102 +72,87 @@ log_open(path, flags, mode, dbenv, lpp)
         * file names there.  Make it fairly large so that we don't have to
         * grow it.
         */
-       len = 30 * 1024;
+#define        DEF_LOG_SIZE    (30 * 1024)
 
        /* Map in the region. */
-       retry_cnt = newregion = 0;
-retry: if (LF_ISSET(DB_CREATE)) {
-               ret = __db_rcreate(dbenv, DB_APP_LOG, path,
-                   DB_DEFAULT_LOG_FILE, mode, len, 0, &fd, &dblp->maddr);
-               if (ret == 0) {
-                       /* Put the LOG structure first in the region. */
-                       lp = dblp->maddr;
-
-                       /* Initialize the rest of the region as free space. */
-                       dblp->addr = (u_int8_t *)dblp->maddr + sizeof(LOG);
-                       __db_shalloc_init(dblp->addr, len - sizeof(LOG));
-
-                       /* Initialize the LOG structure. */
-                       lp->persist.lg_max = dbenv == NULL ? 0 : dbenv->lg_max;
-                       if (lp->persist.lg_max == 0)
-                               lp->persist.lg_max = DEFAULT_MAX;
-                       lp->persist.magic = DB_LOGMAGIC;
-                       lp->persist.version = DB_LOGVERSION;
-                       lp->persist.mode = mode;
-                       SH_TAILQ_INIT(&lp->fq);
-
-                       /* Initialize LOG LSNs. */
-                       lp->lsn.file = 1;
-                       lp->lsn.offset = 0;
-
-                       newregion = 1;
-               } else if (ret != EEXIST)
+       dblp->reginfo.dbenv = dbenv;
+       dblp->reginfo.appname = DB_APP_LOG;
+       if (path == NULL)
+               dblp->reginfo.path = NULL;
+       else
+               if ((dblp->reginfo.path = __db_strdup(path)) == NULL)
                        goto err;
-       }
-
-       /* If we didn't or couldn't create the region, try and join it. */
-       if (!newregion &&
-           (ret = __db_ropen(dbenv, DB_APP_LOG,
-           path, DB_DEFAULT_LOG_FILE, 0, &fd, &dblp->maddr)) != 0) {
-               /*
-                * If we fail because the file isn't available, wait a
-                * second and try again.
-                */
-               if (ret == EAGAIN && ++retry_cnt < 3) {
-                       (void)__db_sleep(1, 0);
-                       goto retry;
-               }
+       dblp->reginfo.file = DB_DEFAULT_LOG_FILE;
+       dblp->reginfo.mode = mode;
+       dblp->reginfo.size = DEF_LOG_SIZE;
+       dblp->reginfo.dbflags = flags;
+       dblp->reginfo.flags = REGION_SIZEDEF;
+       if ((ret = __db_rattach(&dblp->reginfo)) != 0)
                goto err;
-       }
 
-       /* Set up the common information. */
-       dblp->lp = dblp->maddr;
-       dblp->addr = (u_int8_t *)dblp->maddr + sizeof(LOG);
-       dblp->fd = fd;
+       /*
+        * The LOG structure is first in the region, the rest of the region
+        * is free space.
+        */
+       dblp->lp = dblp->reginfo.addr;
+       dblp->addr = (u_int8_t *)dblp->lp + sizeof(LOG);
+
+       /* Initialize a created region. */
+       if (F_ISSET(&dblp->reginfo, REGION_CREATED)) {
+               __db_shalloc_init(dblp->addr, DEF_LOG_SIZE - sizeof(LOG));
+
+               /* Initialize the LOG structure. */
+               lp = dblp->lp;
+               lp->persist.lg_max = dbenv == NULL ? 0 : dbenv->lg_max;
+               if (lp->persist.lg_max == 0)
+                       lp->persist.lg_max = DEFAULT_MAX;
+               lp->persist.magic = DB_LOGMAGIC;
+               lp->persist.version = DB_LOGVERSION;
+               lp->persist.mode = mode;
+               SH_TAILQ_INIT(&lp->fq);
+
+               /* Initialize LOG LSNs. */
+               lp->lsn.file = 1;
+               lp->lsn.offset = 0;
+       }
 
-       /* Initialize thread information. */
+       /* Initialize thread information, mutex. */
        if (LF_ISSET(DB_THREAD)) {
                F_SET(dblp, DB_AM_THREAD);
-
-               if (!newregion)
-                       LOCK_LOGREGION(dblp);
                if ((ret = __db_shalloc(dblp->addr,
-                   sizeof(db_mutex_t), MUTEX_ALIGNMENT, &dblp->mutexp)) == 0)
-                       (void)__db_mutex_init(dblp->mutexp, -1);
-               if (!newregion)
-                       UNLOCK_LOGREGION(dblp);
-               if (ret != 0) {
-                       (void)log_close(dblp);
-                       if (newregion)
-                               (void)log_unlink(path, 1, dbenv);
-                       return (ret);
-               }
+                   sizeof(db_mutex_t), MUTEX_ALIGNMENT, &dblp->mutexp)) != 0)
+                       goto err;
+               (void)__db_mutex_init(dblp->mutexp, -1);
        }
 
        /*
-        * If doing recovery, try and recover any previous log files
-        * before releasing the lock.
+        * If doing recovery, try and recover any previous log files before
+        * releasing the lock.
         */
-       if (newregion) {
-               ret = __log_recover(dblp);
-               UNLOCK_LOGREGION(dblp);
+       if (F_ISSET(&dblp->reginfo, REGION_CREATED) &&
+           (ret = __log_recover(dblp)) != 0)
+               goto err;
 
-               if (ret != 0) {
-                       (void)log_close(dblp);
-                       (void)log_unlink(path, 1, dbenv);
-                       return (ret);
-               }
-       }
+       UNLOCK_LOGREGION(dblp);
        *lpp = dblp;
        return (0);
 
-err:   /*
-        * We never get here with an allocated thread-mutex, so we do
-        * not have to worry about freeing it.
-        */
-       FREE(dblp, sizeof(DB_LOG));
-       return (ret);
+err:   if (dblp->reginfo.addr != NULL) {
+               if (dblp->mutexp != NULL)
+                       __db_shalloc_free(dblp->addr, dblp->mutexp);
+
+               UNLOCK_LOGREGION(dblp);
+               (void)__db_rdetach(&dblp->reginfo);
+               if (F_ISSET(&dblp->reginfo, REGION_CREATED))
+                       (void)log_unlink(path, 1, dbenv);
+       }
 
+       if (dblp->reginfo.path != NULL)
+               FREES(dblp->reginfo.path);
+       if (dblp->dir != NULL)
+               FREES(dblp->dir);
+       FREE(dblp, sizeof(*dblp));
+       return (ret);
 }
 
 /*
@@ -234,7 +206,7 @@ __log_recover(dblp)
                        continue;
                memcpy(&chk, dbt.data, sizeof(u_int32_t));
                if (chk == DB_txn_ckp) {
-                       lp->c_lsn = lsn;
+                       lp->chkpt_lsn = lsn;
                        found_checkpoint = 1;
                }
        }
@@ -273,7 +245,7 @@ __log_recover(dblp)
                                continue;
                        memcpy(&chk, dbt.data, sizeof(u_int32_t));
                        if (chk == DB_txn_ckp) {
-                               lp->c_lsn = lsn;
+                               lp->chkpt_lsn = lsn;
                                found_checkpoint = 1;
                        }
                }
@@ -281,7 +253,7 @@ __log_recover(dblp)
 
        /* If we never find a checkpoint, that's okay, just 0 it out. */
        if (!found_checkpoint)
-               ZERO_LSN(lp->c_lsn);
+               ZERO_LSN(lp->chkpt_lsn);
 
        __db_err(dblp->dbenv,
            "Recovering the log: last valid LSN: file: %lu offset %lu",
@@ -380,7 +352,7 @@ __log_valid(dblp, lp, cnt)
        if ((ret = __db_open(p,
            DB_RDONLY | DB_SEQUENTIAL,
            DB_RDONLY | DB_SEQUENTIAL, 0, &fd)) != 0 ||
-           (ret = __db_seek(fd, 0, 0, sizeof(HDR), SEEK_SET)) != 0 ||
+           (ret = __db_seek(fd, 0, 0, sizeof(HDR), 0, SEEK_SET)) != 0 ||
            (ret = __db_read(fd, &persist, sizeof(LOGP), &nw)) != 0 ||
            nw != sizeof(LOGP)) {
                if (ret == 0)
@@ -429,8 +401,6 @@ log_close(dblp)
 {
        int ret, t_ret;
 
-       ret = 0;
-
        /* Discard the per-thread pointer. */
        if (dblp->mutexp != NULL) {
                LOCK_LOGREGION(dblp);
@@ -439,9 +409,7 @@ log_close(dblp)
        }
 
        /* Close the region. */
-       if ((t_ret =
-           __db_rclose(dblp->dbenv, dblp->fd, dblp->maddr)) != 0 && ret == 0)
-               ret = t_ret;
+       ret = __db_rdetach(&dblp->reginfo);
 
        /* Close open files, release allocated memory. */
        if (dblp->lfd != -1 && (t_ret = __db_close(dblp->lfd)) != 0 && ret == 0)
@@ -456,8 +424,9 @@ log_close(dblp)
        if (dblp->dir != NULL)
                FREES(dblp->dir);
 
-       /* Free the structure. */
-       FREE(dblp, sizeof(DB_LOG));
+       if (dblp->reginfo.path != NULL)
+               FREES(dblp->reginfo.path);
+       FREE(dblp, sizeof(*dblp));
 
        return (ret);
 }
@@ -472,8 +441,19 @@ log_unlink(path, force, dbenv)
        int force;
        DB_ENV *dbenv;
 {
-       return (__db_runlink(dbenv,
-           DB_APP_LOG, path, DB_DEFAULT_LOG_FILE, force));
+       REGINFO reginfo;
+       int ret;
+
+       memset(&reginfo, 0, sizeof(reginfo));
+       reginfo.dbenv = dbenv;
+       reginfo.appname = DB_APP_LOG;
+       if (path != NULL && (reginfo.path = __db_strdup(path)) == NULL)
+               return (ENOMEM);
+       reginfo.file = DB_DEFAULT_LOG_FILE;
+       ret = __db_runlink(&reginfo, force);
+       if (reginfo.path != NULL)
+               FREES(reginfo.path);
+       return (ret);
 }
 
 /*
@@ -511,6 +491,9 @@ log_stat(dblp, gspp, db_malloc)
        (*gspp)->st_cur_file = lp->lsn.file;
        (*gspp)->st_cur_offset = lp->lsn.offset;
 
+       (*gspp)->st_refcnt = lp->rlayout.refcnt;
+       (*gspp)->st_regsize = lp->rlayout.size;
+
        UNLOCK_LOGREGION(dblp);
 
        return (0);
index f3d9f32..12883bd 100644 (file)
@@ -1,43 +1,12 @@
 /*-
  * See the file LICENSE for redistribution information.
  *
- * Copyright (c) 1996, 1997
+ * Copyright (c) 1996, 1997, 1998
  *     Sleepycat Software.  All rights reserved.
  *
- *     @(#)log.src     10.4 (Sleepycat) 1/17/98
- *
- * This is the source file used to create the logging functions for the
- * log package.  Each access method (or set of routines wishing to register
- * record types with the transaction system) should have a file like this.
- * Each type of log record and its parameters is defined.  The basic
- * format of a record definition is:
- *
- * BEGIN       <RECORD_TYPE>
- * ARG|STRING|POINTER  <variable name> <variable type> <printf format>
- * ...
- * END
- * ARG the argument is a simple parameter of the type *        specified.
- * DBT the argument is a DBT (db.h) containing a length and pointer.
- * PTR the argument is a pointer to the data type specified; the entire
- *     type should be logged.
- *
- * There are a set of shell scripts of the form xxx.sh that generate c
- * code and or h files to process these.  (This is probably better done
- * in a single PERL script, but for now, this works.)
- *
- * The DB recovery system requires the following three fields appear in
- * every record, and will assign them to the per-record-type structures
- * as well as making them the first parameters to the appropriate logging
- * call.
- * rectype:    record-type, identifies the structure and log/read call
- * txnid:      transaction id, a DBT in this implementation
- * prev:       the last LSN for this transaction
+ *     @(#)log.src     10.5 (Sleepycat) 4/10/98
  */
 
-/*
- * Use the argument of PREFIX as the prefix for all record types,
- * routines, id numbers, etc.
- */
 PREFIX log
 
 /* Used for registering name/id translations at open or close. */
index 91ae5ab..7db0cc3 100644 (file)
@@ -1,14 +1,14 @@
 /*-
  * See the file LICENSE for redistribution information.
  *
- * Copyright (c) 1997
+ * Copyright (c) 1997, 1998
  *     Sleepycat Software.  All rights reserved.
  */
 
 #include "config.h"
 
 #ifndef lint
-static const char sccsid[] = "@(#)log_archive.c        10.30 (Sleepycat) 1/8/98";
+static const char sccsid[] = "@(#)log_archive.c        10.37 (Sleepycat) 5/3/98";
 #endif /* not lint */
 
 #ifndef NO_SYSTEM_INCLUDES
@@ -24,8 +24,8 @@ static const char sccsid[] = "@(#)log_archive.c       10.30 (Sleepycat) 1/8/98";
 #include "db_dispatch.h"
 #include "shqueue.h"
 #include "log.h"
-#include "clib_ext.h"
 #include "common_ext.h"
+#include "clib_ext.h"                  /* XXX: needed for getcwd. */
 
 static int __absname __P((char *, char *, char **));
 static int __build_data __P((DB_LOG *, char *, char ***, void *(*)(size_t)));
@@ -40,7 +40,7 @@ int
 log_archive(dblp, listp, flags, db_malloc)
        DB_LOG *dblp;
        char ***listp;
-       int flags;
+       u_int32_t flags;
        void *(*db_malloc) __P((size_t));
 {
        DBT rec;
@@ -89,6 +89,11 @@ log_archive(dblp, listp, flags, db_malloc)
                break;
        case 0:
                if ((ret = __log_findckp(dblp, &stable_lsn)) != 0) {
+                       /*
+                        * A return of DB_NOTFOUND means that we didn't find
+                        * any records in the log (so we are not going to be
+                        * deleting any log files).
+                        */
                        if (ret != DB_NOTFOUND)
                                return (ret);
                        *listp = NULL;
@@ -269,7 +274,7 @@ lg_free:            if (F_ISSET(&rec, DB_DBT_MALLOC) && rec.data != NULL)
 
                /* Get the real name. */
                if ((ret = __db_appname(dblp->dbenv,
-                   DB_APP_DATA, NULL, array[last], NULL, &real_name)) != 0)
+                   DB_APP_DATA, NULL, array[last], 0, NULL, &real_name)) != 0)
                        goto err2;
 
                /* If the file doesn't exist, ignore it. */
@@ -335,21 +340,25 @@ __absname(pref, name, newnamep)
        char *pref, *name, **newnamep;
 {
        size_t l_pref, l_name;
+       int isabspath;
        char *newname;
 
-       l_pref = strlen(pref);
        l_name = strlen(name);
+       isabspath = __db_abspath(name);
+       l_pref = isabspath ? 0 : strlen(pref);
 
        /* Malloc space for concatenating the two. */
-       if ((newname = (char *)__db_malloc(l_pref + l_name + 2)) == NULL)
+       if ((*newnamep =
+           newname = (char *)__db_malloc(l_pref + l_name + 2)) == NULL)
                return (ENOMEM);
 
-       /* Build the name. */
-       memcpy(newname, pref, l_pref);
-       if (strchr(PATH_SEPARATOR, newname[l_pref - 1]) == NULL)
-               newname[l_pref++] = PATH_SEPARATOR[0];
+       /* Build the name.  If `name' is an absolute path, ignore any prefix. */
+       if (!isabspath) {
+               memcpy(newname, pref, l_pref);
+               if (strchr(PATH_SEPARATOR, newname[l_pref - 1]) == NULL)
+                       newname[l_pref++] = PATH_SEPARATOR[0];
+       }
        memcpy(newname + l_pref, name, l_name + 1);
-       *newnamep = newname;
 
        return (0);
 }
@@ -409,5 +418,5 @@ static int
 __cmpfunc(p1, p2)
        const void *p1, *p2;
 {
-       return (strcmp(*((char **)p1), *((char **)p2)));
+       return (strcmp(*((char * const *)p1), *((char * const *)p2)));
 }
index 2fe1783..b17b1ff 100644 (file)
@@ -15,8 +15,6 @@
 #include "db_dispatch.h"
 #include "log.h"
 #include "db_am.h"
-#include "common_ext.h"
-
 /*
  * PUBLIC: int __log_register_log
  * PUBLIC:     __P((DB_LOG *, DB_TXN *, DB_LSN *, u_int32_t,
@@ -92,7 +90,7 @@ int __log_register_log(logp, txnid, ret_lsnp, flags,
        bp += sizeof(id);
        memcpy(bp, &ftype, sizeof(ftype));
        bp += sizeof(ftype);
-#ifdef DEBUG
+#ifdef DIAGNOSTIC
        if ((u_int32_t)(bp - (u_int8_t *)logrec.data) != logrec.size)
                fprintf(stderr, "Error in log record length");
 #endif
@@ -108,22 +106,23 @@ int __log_register_log(logp, txnid, ret_lsnp, flags,
  * PUBLIC:    __P((DB_LOG *, DBT *, DB_LSN *, int, void *));
  */
 int
-__log_register_print(notused1, dbtp, lsnp, notused3, notused4)
+__log_register_print(notused1, dbtp, lsnp, notused2, notused3)
        DB_LOG *notused1;
        DBT *dbtp;
        DB_LSN *lsnp;
-       int notused3;
-       void *notused4;
+       int notused2;
+       void *notused3;
 {
        __log_register_args *argp;
        u_int32_t i;
-       int c, ret;
+       u_int ch;
+       int ret;
 
        i = 0;
-       c = 0;
+       ch = 0;
        notused1 = NULL;
-       notused3 = 0;
-       notused4 = NULL;
+       notused2 = 0;
+       notused3 = NULL;
 
        if ((ret = __log_register_read(dbtp->data, &argp)) != 0)
                return (ret);
@@ -137,20 +136,20 @@ __log_register_print(notused1, dbtp, lsnp, notused3, notused4)
        printf("\topcode: %lu\n", (u_long)argp->opcode);
        printf("\tname: ");
        for (i = 0; i < argp->name.size; i++) {
-               c = ((char *)argp->name.data)[i];
-               if (isprint(c) || c == 0xa)
-                       putchar(c);
+               ch = ((u_int8_t *)argp->name.data)[i];
+               if (isprint(ch) || ch == 0xa)
+                       putchar(ch);
                else
-                       printf("%#x ", c);
+                       printf("%#x ", ch);
        }
        printf("\n");
        printf("\tuid: ");
        for (i = 0; i < argp->uid.size; i++) {
-               c = ((char *)argp->uid.data)[i];
-               if (isprint(c) || c == 0xa)
-                       putchar(c);
+               ch = ((u_int8_t *)argp->uid.data)[i];
+               if (isprint(ch) || ch == 0xa)
+                       putchar(ch);
                else
-                       printf("%#x ", c);
+                       printf("%#x ", ch);
        }
        printf("\n");
        printf("\tid: %lu\n", (u_long)argp->id);
index 601b25c..320b34a 100644 (file)
@@ -1,13 +1,13 @@
 /*-
  * See the file LICENSE for redistribution information.
  *
- * Copyright (c) 1996, 1997
+ * Copyright (c) 1996, 1997, 1998
  *     Sleepycat Software.  All rights reserved.
  */
 #include "config.h"
 
 #ifndef lint
-static const char sccsid[] = "@(#)log_compare.c        10.2 (Sleepycat) 6/21/97";
+static const char sccsid[] = "@(#)log_compare.c        10.3 (Sleepycat) 4/10/98";
 #endif /* not lint */
 
 #ifndef NO_SYSTEM_INCLUDES
index 115a00e..82bd589 100644 (file)
@@ -1,21 +1,20 @@
 /*-
  * See the file LICENSE for redistribution information.
  *
- * Copyright (c) 1996, 1997
+ * Copyright (c) 1996, 1997, 1998
  *     Sleepycat Software.  All rights reserved.
  */
 
 #include "config.h"
 
 #ifndef lint
-static const char sccsid[] = "@(#)log_findckp.c        10.12 (Sleepycat) 10/25/97";
+static const char sccsid[] = "@(#)log_findckp.c        10.15 (Sleepycat) 4/26/98";
 #endif /* not lint */
 
 #ifndef NO_SYSTEM_INCLUDES
 #include <sys/types.h>
 
 #include <errno.h>
-#include <stdlib.h>
 #include <string.h>
 #endif
 
@@ -44,10 +43,10 @@ static const char sccsid[] = "@(#)log_findckp.c     10.12 (Sleepycat) 10/25/97";
  * We find one at 500.  This means that we can truncate the log before
  * 500 or run recovery beginning at 500.
  *
- * Returns 0 if we find a checkpoint.
+ * Returns 0 if we find a suitable checkpoint or we retrieved the
+ * first record in the log from which to start.
+ * Returns DB_NOTFOUND if there are no log records.
  * Returns errno on error.
- * Returns DB_NOTFOUND if we could not find a suitable start point and
- * we should start from the beginning.
  *
  * PUBLIC: int __log_findckp __P((DB_LOG *, DB_LSN *));
  */
@@ -70,9 +69,12 @@ __log_findckp(lp, lsnp)
        memset(&data, 0, sizeof(data));
        if (F_ISSET(lp, DB_AM_THREAD))
                F_SET(&data, DB_DBT_MALLOC);
-       if ((ret = log_get(lp, &last_ckp, &data, DB_CHECKPOINT)) != 0)
-               return (ret == ENOENT ? DB_NOTFOUND : ret);
        ZERO_LSN(ckp_lsn);
+       if ((ret = log_get(lp, &last_ckp, &data, DB_CHECKPOINT)) != 0)
+               if (ret == ENOENT)
+                       goto get_first;
+               else
+                       return (ret);
 
        next_lsn = last_ckp;
        do {
@@ -115,16 +117,12 @@ __log_findckp(lp, lsnp)
         * beginning of the log.
         */
        if (log_compare(&last_ckp, &ckp_lsn) > 0) {
-               if ((ret = log_get(lp, &last_ckp, &data, DB_FIRST)) != 0)
+get_first:     if ((ret = log_get(lp, &last_ckp, &data, DB_FIRST)) != 0)
                        return (ret);
                if (F_ISSET(lp, DB_AM_THREAD))
                        __db_free(data.data);
        }
        *lsnp = last_ckp;
 
-       if (verbose)
-               __db_err(lp->dbenv, "Rolling forward from [%lu][%lu]",
-                       (u_long)last_ckp.file, (u_long)last_ckp.offset);
-
        return (IS_ZERO_LSN(last_ckp) ? DB_NOTFOUND : 0);
 }
index ab6f624..9a055de 100644 (file)
@@ -1,21 +1,19 @@
 /*-
  * See the file LICENSE for redistribution information.
  *
- * Copyright (c) 1996, 1997
+ * Copyright (c) 1996, 1997, 1998
  *     Sleepycat Software.  All rights reserved.
  */
 #include "config.h"
 
 #ifndef lint
-static const char sccsid[] = "@(#)log_get.c    10.24 (Sleepycat) 1/17/98";
+static const char sccsid[] = "@(#)log_get.c    10.32 (Sleepycat) 5/6/98";
 #endif /* not lint */
 
 #ifndef NO_SYSTEM_INCLUDES
 #include <sys/types.h>
 
 #include <errno.h>
-#include <fcntl.h>
-#include <stdlib.h>
 #include <string.h>
 #include <unistd.h>
 #endif
@@ -36,9 +34,8 @@ log_get(dblp, alsn, dbt, flags)
        DB_LOG *dblp;
        DB_LSN *alsn;
        DBT *dbt;
-       int flags;
+       u_int32_t flags;
 {
-       LOG *lp;
        int ret;
 
        /* Validate arguments. */
@@ -66,8 +63,6 @@ log_get(dblp, alsn, dbt, flags)
                        return (__db_ferr(dblp->dbenv, "threaded data", 1));
        }
 
-       lp = dblp->lp;
-
        LOCK_LOGREGION(dblp);
 
        /*
@@ -97,14 +92,15 @@ log_get(dblp, alsn, dbt, flags)
  * __log_get --
  *     Get a log record; internal version.
  *
- * PUBLIC: int __log_get __P((DB_LOG *, DB_LSN *, DBT *, int, int));
+ * PUBLIC: int __log_get __P((DB_LOG *, DB_LSN *, DBT *, u_int32_t, int));
  */
 int
 __log_get(dblp, alsn, dbt, flags, silent)
        DB_LOG *dblp;
        DB_LSN *alsn;
        DBT *dbt;
-       int flags, silent;
+       u_int32_t flags;
+       int silent;
 {
        DB_LSN nlsn;
        HDR hdr;
@@ -122,7 +118,7 @@ __log_get(dblp, alsn, dbt, flags, silent)
        nlsn = dblp->c_lsn;
        switch (flags) {
        case DB_CHECKPOINT:
-               nlsn = lp->c_lsn;
+               nlsn = lp->chkpt_lsn;
                if (IS_ZERO_LSN(nlsn)) {
                        __db_err(dblp->dbenv,
        "log_get: unable to find checkpoint record: no checkpoint set.");
@@ -219,7 +215,8 @@ retry:
        }
 
        /* Seek to the header offset and read the header. */
-       if ((ret = __db_seek(dblp->c_fd, 0, 0, nlsn.offset, SEEK_SET)) != 0) {
+       if ((ret =
+           __db_seek(dblp->c_fd, 0, 0, nlsn.offset, 0, SEEK_SET)) != 0) {
                fail = "seek";
                goto err1;
        }
@@ -272,7 +269,13 @@ retry:
                goto cksum;
        }
 
-       /* Allocate temporary memory to hold the record. */
+       /*
+        * Allocate temporary memory to hold the record.
+        *
+        * XXX
+        * We're calling malloc(3) with a region locked.  This isn't
+        * a good idea.
+        */
        if ((tbuf = (char *)__db_malloc(len)) == NULL) {
                ret = ENOMEM;
                goto err1;
index 65a3990..d00e7dd 100644 (file)
@@ -1,21 +1,19 @@
 /*-
  * See the file LICENSE for redistribution information.
  *
- * Copyright (c) 1996, 1997
+ * Copyright (c) 1996, 1997, 1998
  *     Sleepycat Software.  All rights reserved.
  */
 #include "config.h"
 
 #ifndef lint
-static const char sccsid[] = "@(#)log_put.c    10.24 (Sleepycat) 1/17/98";
+static const char sccsid[] = "@(#)log_put.c    10.35 (Sleepycat) 5/6/98";
 #endif /* not lint */
 
 #ifndef NO_SYSTEM_INCLUDES
 #include <sys/types.h>
 
 #include <errno.h>
-#include <fcntl.h>
-#include <stdlib.h>
 #include <string.h>
 #include <time.h>
 #include <unistd.h>
@@ -43,18 +41,19 @@ log_put(dblp, lsn, dbt, flags)
        DB_LOG *dblp;
        DB_LSN *lsn;
        const DBT *dbt;
-       int flags;
+       u_int32_t flags;
 {
        int ret;
 
        /* Validate arguments. */
-#define        OKFLAGS (DB_CHECKPOINT | DB_FLUSH)
+#define        OKFLAGS (DB_CHECKPOINT | DB_FLUSH | DB_CURLSN)
        if (flags != 0) {
                if ((ret =
                    __db_fchk(dblp->dbenv, "log_put", flags, OKFLAGS)) != 0)
                        return (ret);
                switch (flags) {
                case DB_CHECKPOINT:
+               case DB_CURLSN:
                case DB_FLUSH:
                case 0:
                        break;
@@ -73,14 +72,14 @@ log_put(dblp, lsn, dbt, flags)
  * __log_put --
  *     Write a log record; internal version.
  *
- * PUBLIC: int __log_put __P((DB_LOG *, DB_LSN *, const DBT *, int));
+ * PUBLIC: int __log_put __P((DB_LOG *, DB_LSN *, const DBT *, u_int32_t));
  */
 int
 __log_put(dblp, lsn, dbt, flags)
        DB_LOG *dblp;
        DB_LSN *lsn;
        const DBT *dbt;
-       int flags;
+       u_int32_t flags;
 {
        DBT fid_dbt, t;
        DB_LSN r_unused;
@@ -91,6 +90,17 @@ __log_put(dblp, lsn, dbt, flags)
 
        lp = dblp->lp;
 
+       /*
+        * If the application just wants to know where we are, fill in
+        * the information.  Currently used by the transaction manager
+        * to avoid writing TXN_begin records.
+        */
+       if (LF_ISSET(DB_CURLSN)) {
+               lsn->file = lp->lsn.file;
+               lsn->offset = lp->lsn.offset;
+               return (0);
+       }
+
        /* If this information won't fit in the file, swap files. */
        if (lp->lsn.offset + sizeof(HDR) + dbt->size > lp->persist.lg_max) {
                if (sizeof(HDR) +
@@ -151,7 +161,7 @@ __log_put(dblp, lsn, dbt, flags)
         *      Append the set of file name information into the log.
         */
        if (flags == DB_CHECKPOINT) {
-               lp->c_lsn = *lsn;
+               lp->chkpt_lsn = *lsn;
 
                for (fnp = SH_TAILQ_FIRST(&dblp->lp->fq, __fname);
                    fnp != NULL; fnp = SH_TAILQ_NEXT(fnp, q, __fname)) {
@@ -159,7 +169,7 @@ __log_put(dblp, lsn, dbt, flags)
                        t.data = R_ADDR(dblp, fnp->name_off);
                        t.size = strlen(t.data) + 1;
                        memset(&fid_dbt, 0, sizeof(fid_dbt));
-                       fid_dbt.data = R_ADDR(dblp, fnp->fileid_off);
+                       fid_dbt.data = fnp->ufid;
                        fid_dbt.size = DB_FILE_ID_LEN;
                        if ((ret = __log_register_log(dblp, NULL, &r_unused, 0,
                            LOG_CHECKPOINT, &t, &fid_dbt, fnp->id, fnp->s_type))
@@ -324,7 +334,11 @@ __log_flush(dblp, lsn)
         */
        lp->s_lsn = lp->f_lsn;
        if (!current)
-               --lp->s_lsn.offset;
+               if (lp->s_lsn.offset == 0) {
+                       --lp->s_lsn.file;
+                       lp->s_lsn.offset = lp->persist.lg_max;
+               } else
+                       --lp->s_lsn.offset;
 
        return (0);
 }
@@ -416,7 +430,7 @@ __log_write(dblp, addr, len)
         * Seek to the offset in the file (someone may have written it
         * since we last did).
         */
-       if ((ret = __db_seek(dblp->lfd, 0, 0, lp->w_off, SEEK_SET)) != 0)
+       if ((ret = __db_seek(dblp->lfd, 0, 0, lp->w_off, 0, SEEK_SET)) != 0)
                return (ret);
        if ((ret = __db_write(dblp->lfd, addr, len, &nw)) != 0)
                return (ret);
@@ -461,7 +475,7 @@ log_file(dblp, lsn, namep, len)
                return (ret);
 
        /* Check to make sure there's enough room and copy the name. */
-       if (len < strlen(p)) {
+       if (len < strlen(p) + 1) {
                *namep = '\0';
                return (ENOMEM);
        }
@@ -518,5 +532,5 @@ __log_name(dblp, filenumber, namep)
 
        (void)snprintf(name, sizeof(name), LFNAME, filenumber);
        return (__db_appname(dblp->dbenv,
-           DB_APP_LOG, dblp->dir, name, NULL, namep));
+           DB_APP_LOG, dblp->dir, name, 0, NULL, namep));
 }
index 69334f8..5deac46 100644 (file)
@@ -1,7 +1,7 @@
 /*-
  * See the file LICENSE for redistribution information.
  *
- * Copyright (c) 1996, 1997
+ * Copyright (c) 1996, 1997, 1998
  *     Sleepycat Software.  All rights reserved.
  */
 /*
 #include "config.h"
 
 #ifndef lint
-static const char sccsid[] = "@(#)log_rec.c    10.16 (Sleepycat) 1/17/98";
+static const char sccsid[] = "@(#)log_rec.c    10.20 (Sleepycat) 4/28/98";
 #endif /* not lint */
 
 #ifndef NO_SYSTEM_INCLUDES
 #include <sys/types.h>
 
 #include <errno.h>
-#include <fcntl.h>
-#include <stddef.h>
-#include <stdlib.h>
 #include <string.h>
 #endif
 
@@ -90,7 +87,7 @@ __log_register_recover(logp, dbtp, lsnp, redo, info)
 
        if ((argp->opcode == LOG_CHECKPOINT && redo == TXN_OPENFILES) ||
            (argp->opcode == LOG_OPEN &&
-           (redo == TXN_REDO || redo == TXN_OPENFILES || 
+           (redo == TXN_REDO || redo == TXN_OPENFILES ||
             redo == TXN_FORWARD_ROLL)) ||
            (argp->opcode == LOG_CLOSE &&
            (redo == TXN_UNDO || redo == TXN_BACKWARD_ROLL))) {
@@ -121,6 +118,7 @@ __log_register_recover(logp, dbtp, lsnp, redo, info)
                        if (!logp->dbentry[argp->id].deleted)
                                ret = EINVAL;
                } else if (--logp->dbentry[argp->id].refcount == 0) {
+                       F_SET(logp->dbentry[argp->id].dbp, DB_AM_RECOVER);
                        ret = logp->dbentry[argp->id].dbp->close(
                            logp->dbentry[argp->id].dbp, 0);
                        logp->dbentry[argp->id].dbp = NULL;
index 9907d6e..a6fc4c1 100644 (file)
@@ -1,20 +1,19 @@
 /*-
  * See the file LICENSE for redistribution information.
  *
- * Copyright (c) 1996, 1997
+ * Copyright (c) 1996, 1997, 1998
  *     Sleepycat Software.  All rights reserved.
  */
 #include "config.h"
 
 #ifndef lint
-static const char sccsid[] = "@(#)log_register.c       10.14 (Sleepycat) 1/19/98";
+static const char sccsid[] = "@(#)log_register.c       10.18 (Sleepycat) 5/3/98";
 #endif /* not lint */
 
 #ifndef NO_SYSTEM_INCLUDES
 #include <sys/types.h>
 
 #include <errno.h>
-#include <stdlib.h>
 #include <string.h>
 #endif
 
@@ -42,12 +41,12 @@ log_register(dblp, dbp, name, type, idp)
        u_int32_t fid;
        int inserted, ret;
        char *fullname;
-       void *fidp, *namep;
+       void *namep;
 
        fid = 0;
        inserted = 0;
        fullname = NULL;
-       fnp = fidp = namep = NULL;
+       fnp = namep = NULL;
 
        /* Check the arguments. */
        if (type != DB_BTREE && type != DB_HASH && type != DB_RECNO) {
@@ -57,7 +56,7 @@ log_register(dblp, dbp, name, type, idp)
 
        /* Get the log file id. */
        if ((ret = __db_appname(dblp->dbenv,
-           DB_APP_DATA, NULL, name, NULL, &fullname)) != 0)
+           DB_APP_DATA, NULL, name, 0, NULL, &fullname)) != 0)
                return (ret);
 
        LOCK_LOGREGION(dblp);
@@ -70,8 +69,7 @@ log_register(dblp, dbp, name, type, idp)
            fnp != NULL; fnp = SH_TAILQ_NEXT(fnp, q, __fname)) {
                if (fid <= fnp->id)
                        fid = fnp->id + 1;
-               if (!memcmp(dbp->lock.fileid,
-                   R_ADDR(dblp, fnp->fileid_off), DB_FILE_ID_LEN)) {
+               if (!memcmp(dbp->lock.fileid, fnp->ufid, DB_FILE_ID_LEN)) {
                        ++fnp->ref;
                        fid = fnp->id;
                        goto found;
@@ -84,15 +82,7 @@ log_register(dblp, dbp, name, type, idp)
        fnp->ref = 1;
        fnp->id = fid;
        fnp->s_type = type;
-
-       if ((ret = __db_shalloc(dblp->addr, DB_FILE_ID_LEN, 0, &fidp)) != 0)
-               goto err;
-       /*
-        * XXX Now that uids are fixed size, we can put them in the fnp
-        * structure.
-        */
-       fnp->fileid_off = R_OFFSET(dblp, fidp);
-       memcpy(fidp, dbp->lock.fileid, DB_FILE_ID_LEN);
+       memcpy(fnp->ufid, dbp->lock.fileid, DB_FILE_ID_LEN);
 
        len = strlen(name) + 1;
        if ((ret = __db_shalloc(dblp->addr, len, 0, &namep)) != 0)
@@ -126,8 +116,6 @@ err:                /*
                        SH_TAILQ_REMOVE(&dblp->lp->fq, fnp, q, __fname);
                if (namep != NULL)
                        __db_shalloc_free(dblp->addr, namep);
-               if (fidp != NULL)
-                       __db_shalloc_free(dblp->addr, fidp);
                if (fnp != NULL)
                        __db_shalloc_free(dblp->addr, fnp);
        }
@@ -176,7 +164,7 @@ log_unregister(dblp, fid)
                r_name.data = R_ADDR(dblp, fnp->name_off);
                r_name.size = strlen(r_name.data) + 1;
                memset(&fid_dbt, 0, sizeof(fid_dbt));
-               fid_dbt.data =  R_ADDR(dblp, fnp->fileid_off);
+               fid_dbt.data = fnp->ufid;
                fid_dbt.size = DB_FILE_ID_LEN;
                if ((ret = __log_register_log(dblp, NULL, &r_unused,
                    0, LOG_CLOSE, &r_name, &fid_dbt, fid, fnp->s_type)) != 0)
@@ -190,7 +178,6 @@ log_unregister(dblp, fid)
        if (fnp->ref > 1)
                --fnp->ref;
        else {
-               __db_shalloc_free(dblp->addr, R_ADDR(dblp, fnp->fileid_off));
                __db_shalloc_free(dblp->addr, R_ADDR(dblp, fnp->name_off));
                SH_TAILQ_REMOVE(&dblp->lp->fq, fnp, q, __fname);
                __db_shalloc_free(dblp->addr, fnp);
index c23abdd..d89f9c2 100644 (file)
@@ -1,13 +1,13 @@
 /*-
  * See the file LICENSE for redistribution information.
  *
- * Copyright (c) 1996, 1997
+ * Copyright (c) 1996, 1997, 1998
  *     Sleepycat Software.  All rights reserved.
  */
 #include "config.h"
 
 #ifndef lint
-static const char sccsid[] = "@(#)mp_bh.c      10.28 (Sleepycat) 1/8/98";
+static const char sccsid[] = "@(#)mp_bh.c      10.38 (Sleepycat) 5/20/98";
 #endif /* not lint */
 
 #ifndef NO_SYSTEM_INCLUDES
@@ -59,8 +59,10 @@ __memp_bhwrite(dbmp, mfp, bhp, restartp, wrotep)
            dbmfp != NULL; dbmfp = TAILQ_NEXT(dbmfp, q))
                if (dbmfp->mfp == mfp) {
                        if (F_ISSET(dbmfp, MP_READONLY) &&
-                           __memp_upgrade(dbmp, dbmfp, mfp))
+                           __memp_upgrade(dbmp, dbmfp, mfp)) {
+                               UNLOCKHANDLE(dbmp, dbmp->mutexp);
                                return (0);
+                       }
                        break;
                }
        UNLOCKHANDLE(dbmp, dbmp->mutexp);
@@ -111,8 +113,8 @@ __memp_bhwrite(dbmp, mfp, bhp, restartp, wrotep)
        if (F_ISSET(mfp, MP_TEMP))
                return (0);
 
-       if (__memp_fopen(dbmp, mfp, R_ADDR(dbmp, mfp->path_off), mfp->ftype,
-           0, 0, mfp->stat.st_pagesize, 0, NULL, NULL, 0, &dbmfp) != 0)
+       if (__memp_fopen(dbmp, mfp, R_ADDR(dbmp, mfp->path_off),
+           0, 0, mfp->stat.st_pagesize, 0, NULL, &dbmfp) != 0)
                return (0);
 
 found: return (__memp_pgwrite(dbmfp, bhp, restartp, wrotep));
@@ -152,7 +154,7 @@ __memp_pgread(dbmfp, bhp, can_create)
        ret = 0;
        LOCKHANDLE(dbmp, dbmfp->mutexp);
        if (dbmfp->fd == -1 || (ret =
-           __db_seek(dbmfp->fd, pagesize, bhp->pgno, 0, SEEK_SET)) != 0) {
+           __db_seek(dbmfp->fd, pagesize, bhp->pgno, 0, 0, SEEK_SET)) != 0) {
                if (!can_create) {
                        if (dbmfp->fd == -1)
                                ret = EINVAL;
@@ -164,8 +166,17 @@ __memp_pgread(dbmfp, bhp, can_create)
                }
                UNLOCKHANDLE(dbmp, dbmfp->mutexp);
 
-               /* Clear any uninitialized data. */
-               memset(bhp->buf, 0, pagesize);
+               /* Clear the created page. */
+               if (mfp->clear_len == 0)
+                       memset(bhp->buf, 0, pagesize);
+               else {
+                       memset(bhp->buf, 0, mfp->clear_len);
+#ifdef DIAGNOSTIC
+                       memset(bhp->buf + mfp->clear_len,
+                           0xff, pagesize - mfp->clear_len);
+#endif
+               }
+
                goto pgin;
        }
 
@@ -186,8 +197,16 @@ __memp_pgread(dbmfp, bhp, can_create)
                        goto err;
                }
 
-               /* Clear any uninitialized data. */
-               memset(bhp->buf + nr, 0, pagesize - nr);
+               /*
+                * If we didn't fail until we tried the read, don't clear the
+                * whole page, it wouldn't be insane for a filesystem to just
+                * always behave that way.  Else, clear any uninitialized data.
+                */
+               if (nr == 0)
+                       memset(bhp->buf, 0,
+                           mfp->clear_len == 0 ? pagesize : mfp->clear_len);
+               else
+                       memset(bhp->buf + nr, 0, pagesize - nr);
        }
 
        /* Call any pgin function. */
@@ -308,31 +327,31 @@ __memp_pgwrite(dbmfp, bhp, restartp, wrotep)
 
        /* Temporary files may not yet have been created. */
        LOCKHANDLE(dbmp, dbmfp->mutexp);
-       if (dbmfp->fd == -1)
-               if ((ret = __db_appname(dbenv, DB_APP_TMP,
-                   NULL, NULL, &dbmfp->fd, NULL)) != 0 || dbmfp->fd == -1) {
-                       UNLOCKHANDLE(dbmp, dbmfp->mutexp);
-                       __db_err(dbenv,
-                           "unable to create temporary backing file");
-                       goto err;
-               }
+       if (dbmfp->fd == -1 &&
+           ((ret = __db_appname(dbenv, DB_APP_TMP, NULL, NULL,
+           DB_CREATE | DB_EXCL | DB_TEMPORARY, &dbmfp->fd, NULL)) != 0 ||
+           dbmfp->fd == -1)) {
+               UNLOCKHANDLE(dbmp, dbmfp->mutexp);
+               __db_err(dbenv, "unable to create temporary backing file");
+               goto err;
+       }
 
-       /* Write the page out. */
-       if ((ret = __db_seek(dbmfp->fd, pagesize, bhp->pgno, 0, SEEK_SET)) != 0)
+       /*
+        * Write the page out.
+        *
+        * XXX
+        * Shut the compiler up; it doesn't understand the correlation between
+        * the failing clauses to __db_lseek and __db_write and this ret != 0.
+        */
+       COMPQUIET(fail, NULL);
+       if ((ret =
+           __db_seek(dbmfp->fd, pagesize, bhp->pgno, 0, 0, SEEK_SET)) != 0)
                fail = "seek";
        else if ((ret = __db_write(dbmfp->fd, bhp->buf, pagesize, &nw)) != 0)
                fail = "write";
        UNLOCKHANDLE(dbmp, dbmfp->mutexp);
-       if (ret != 0) {
-               /*
-                * XXX
-                * Shut the compiler up; it doesn't understand the correlation
-                * between the failing clauses to __db_lseek and __db_write and
-                * this ret != 0.
-                */
-               COMPQUIET(fail, NULL);
+       if (ret != 0)
                goto syserr;
-       }
 
        if (nw != (ssize_t)pagesize) {
                ret = EIO;
@@ -548,7 +567,7 @@ __memp_upgrade(dbmp, dbmfp, mfp)
         * way we could have gotten a file descriptor of any kind.
         */
        if ((ret = __db_appname(dbmp->dbenv, DB_APP_DATA,
-           NULL, R_ADDR(dbmp, mfp->path_off), NULL, &rpath)) != 0)
+           NULL, R_ADDR(dbmp, mfp->path_off), 0, NULL, &rpath)) != 0)
                return (ret);
        if (__db_open(rpath, 0, 0, 0, &fd) != 0) {
                F_SET(dbmfp, MP_UPGRADE_FAIL);
index f5955c4..c8ae2e9 100644 (file)
@@ -1,21 +1,19 @@
 /*-
  * See the file LICENSE for redistribution information.
  *
- * Copyright (c) 1996, 1997
+ * Copyright (c) 1996, 1997, 1998
  *     Sleepycat Software.  All rights reserved.
  */
 #include "config.h"
 
 #ifndef lint
-static const char sccsid[] = "@(#)mp_fget.c    10.33 (Sleepycat) 12/2/97";
+static const char sccsid[] = "@(#)mp_fget.c    10.48 (Sleepycat) 6/2/98";
 #endif /* not lint */
 
 #ifndef NO_SYSTEM_INCLUDES
 #include <sys/types.h>
-#include <sys/stat.h>
 
 #include <errno.h>
-#include <stdlib.h>
 #include <string.h>
 #endif
 
@@ -25,8 +23,6 @@ static const char sccsid[] = "@(#)mp_fget.c   10.33 (Sleepycat) 12/2/97";
 #include "mp.h"
 #include "common_ext.h"
 
-int __sleep_on_every_page_get;         /* XXX: thread debugging option. */
-
 /*
  * memp_fget --
  *     Get a page from the file.
@@ -35,7 +31,7 @@ int
 memp_fget(dbmfp, pgnoaddr, flags, addrp)
        DB_MPOOLFILE *dbmfp;
        db_pgno_t *pgnoaddr;
-       int flags;
+       u_int32_t flags;
        void *addrp;
 {
        BH *bhp;
@@ -43,11 +39,12 @@ memp_fget(dbmfp, pgnoaddr, flags, addrp)
        MPOOL *mp;
        MPOOLFILE *mfp;
        size_t bucket, mf_offset;
-       u_long cnt;
-       int b_incr, b_inserted, readonly_alloc, ret;
-       void *addr;
+       u_int32_t st_hsearch;
+       int b_incr, first, ret;
 
        dbmp = dbmfp->dbmp;
+       mp = dbmp->mp;
+       mfp = dbmfp->mfp;
 
        /*
         * Validate arguments.
@@ -79,32 +76,62 @@ memp_fget(dbmfp, pgnoaddr, flags, addrp)
                }
        }
 
-#ifdef DEBUG
+#ifdef DIAGNOSTIC
        /*
         * XXX
         * We want to switch threads as often as possible.  Sleep every time
         * we get a new page to make it more likely.
         */
-       if (__sleep_on_every_page_get &&
+       if (DB_GLOBAL(db_pageyield) &&
            (__db_yield == NULL || __db_yield() != 0))
                __db_sleep(0, 1);
 #endif
 
-       mp = dbmp->mp;
-       mfp = dbmfp->mfp;
+       /* Initialize remaining local variables. */
        mf_offset = R_OFFSET(dbmp, mfp);
-       addr = NULL;
        bhp = NULL;
-       b_incr = b_inserted = ret = 0;
+       st_hsearch = 0;
+       b_incr = ret = 0;
+
+       /* Determine the hash bucket where this page will live. */
+       bucket = BUCKET(mp, mf_offset, *pgnoaddr);
 
        LOCKREGION(dbmp);
 
        /*
-        * If mmap'ing the file, just return a pointer.  However, if another
-        * process has opened the file for writing since we mmap'd it, start
-        * playing the game by their rules, i.e. everything goes through the
-        * cache.  All pages previously returned should be safe, as long as
-        * a locking protocol was observed.
+        * Check for the last or last + 1 page requests.
+        *
+        * Examine and update the file's last_pgno value.  We don't care if
+        * the last_pgno value immediately changes due to another thread --
+        * at this instant in time, the value is correct.  We do increment the
+        * current last_pgno value if the thread is asking for a new page,
+        * however, to ensure that two threads creating pages don't get the
+        * same one.
+        */
+       if (LF_ISSET(DB_MPOOL_LAST | DB_MPOOL_NEW)) {
+               if (LF_ISSET(DB_MPOOL_NEW))
+                       ++mfp->last_pgno;
+               *pgnoaddr = mfp->last_pgno;
+               bucket = BUCKET(mp, mf_offset, mfp->last_pgno);
+
+               if (LF_ISSET(DB_MPOOL_NEW))
+                       goto alloc;
+       }
+
+       /*
+        * If mmap'ing the file and the page is not past the end of the file,
+        * just return a pointer.
+        *
+        * The page may be past the end of the file, so check the page number
+        * argument against the original length of the file.  If we previously
+        * returned pages past the original end of the file, last_pgno will
+        * have been updated to match the "new" end of the file, and checking
+        * against it would return pointers past the end of the mmap'd region.
+        *
+        * If another process has opened the file for writing since we mmap'd
+        * it, we will start playing the game by their rules, i.e. everything
+        * goes through the cache.  All pages previously returned will be safe,
+        * as long as the correct locking protocol was observed.
         *
         * XXX
         * We don't discard the map because we don't know when all of the
@@ -112,203 +139,180 @@ memp_fget(dbmfp, pgnoaddr, flags, addrp)
         * It would be possible to do so by reference counting the open
         * pages from the mmap, but it's unclear to me that it's worth it.
         */
-       if (dbmfp->addr != NULL && F_ISSET(dbmfp->mfp, MP_CAN_MMAP)) {
-               readonly_alloc = 0;
-               if (LF_ISSET(DB_MPOOL_LAST))
-                       *pgnoaddr = mfp->last_pgno;
-               else {
+       if (dbmfp->addr != NULL && F_ISSET(mfp, MP_CAN_MMAP))
+               if (*pgnoaddr > mfp->orig_last_pgno) {
                        /*
                         * !!!
-                        * Allocate a page that can never really exist.  See
-                        * the comment above about non-existent pages and the
-                        * hash access method.
+                        * See the comment above about non-existent pages and
+                        * the hash access method.
                         */
-                       if (LF_ISSET(DB_MPOOL_CREATE | DB_MPOOL_NEW))
-                               readonly_alloc = 1;
-                       else if (*pgnoaddr > mfp->last_pgno) {
+                       if (!LF_ISSET(DB_MPOOL_CREATE)) {
                                __db_err(dbmp->dbenv,
                                    "%s: page %lu doesn't exist",
                                    __memp_fn(dbmfp), (u_long)*pgnoaddr);
                                ret = EINVAL;
                                goto err;
                        }
-               }
-               if (!readonly_alloc) {
-                       addr = R_ADDR(dbmfp, *pgnoaddr * mfp->stat.st_pagesize);
-
+               } else {
+                       *(void **)addrp =
+                           R_ADDR(dbmfp, *pgnoaddr * mfp->stat.st_pagesize);
                        ++mp->stat.st_map;
                        ++mfp->stat.st_map;
+                       goto done;
+               }
 
-                       goto mapret;
+       /* Search the hash chain for the page. */
+       for (bhp = SH_TAILQ_FIRST(&dbmp->htab[bucket], __bh);
+           bhp != NULL; bhp = SH_TAILQ_NEXT(bhp, hq, __bh)) {
+               ++st_hsearch;
+               if (bhp->pgno != *pgnoaddr || bhp->mf_offset != mf_offset)
+                       continue;
+
+               /* Increment the reference count. */
+               if (bhp->ref == UINT16_T_MAX) {
+                       __db_err(dbmp->dbenv,
+                           "%s: page %lu: reference count overflow",
+                           __memp_fn(dbmfp), (u_long)bhp->pgno);
+                       ret = EINVAL;
+                       goto err;
                }
-       }
 
-       /* Check if requesting the last page or a new page. */
-       if (LF_ISSET(DB_MPOOL_LAST))
-               *pgnoaddr = mfp->last_pgno;
+               /*
+                * Increment the reference count.  We may discard the region
+                * lock as we evaluate and/or read the buffer, so we need to
+                * ensure that it doesn't move and that its contents remain
+                * unchanged.
+                */
+               ++bhp->ref;
+               b_incr = 1;
 
-       if (LF_ISSET(DB_MPOOL_NEW)) {
-               *pgnoaddr = mfp->last_pgno + 1;
-               goto alloc;
-       }
+               /*
+                * Any buffer we find might be trouble.
+                *
+                * BH_LOCKED --
+                * I/O is in progress.  Because we've incremented the buffer
+                * reference count, we know the buffer can't move.  Unlock
+                * the region lock, wait for the I/O to complete, and reacquire
+                * the region.
+                */
+               for (first = 1; F_ISSET(bhp, BH_LOCKED); first = 0) {
+                       UNLOCKREGION(dbmp);
 
-       /* Check the BH hash bucket queue. */
-       bucket = BUCKET(mp, mf_offset, *pgnoaddr);
-       for (cnt = 0,
-           bhp = SH_TAILQ_FIRST(&dbmp->htab[bucket], __bh);
-           bhp != NULL; bhp = SH_TAILQ_NEXT(bhp, hq, __bh)) {
-               ++cnt;
-               if (bhp->pgno == *pgnoaddr && bhp->mf_offset == mf_offset) {
-                       addr = bhp->buf;
-                       ++mp->stat.st_hash_searches;
-                       if (cnt > mp->stat.st_hash_longest)
-                               mp->stat.st_hash_longest = cnt;
-                       mp->stat.st_hash_examined += cnt;
-                       goto found;
+                       /*
+                        * Explicitly yield the processor if it's not the first
+                        * pass through this loop -- if we don't, we might end
+                        * up running to the end of our CPU quantum as we will
+                        * simply be swapping between the two locks.
+                        */
+                       if (!first && (__db_yield == NULL || __db_yield() != 0))
+                               __db_sleep(0, 1);
+
+                       LOCKBUFFER(dbmp, bhp);
+                       /* Wait for I/O to finish... */
+                       UNLOCKBUFFER(dbmp, bhp);
+                       LOCKREGION(dbmp);
                }
-       }
-       if (cnt != 0) {
-               ++mp->stat.st_hash_searches;
-               if (cnt > mp->stat.st_hash_longest)
-                       mp->stat.st_hash_longest = cnt;
-               mp->stat.st_hash_examined += cnt;
+
+               /*
+                * BH_TRASH --
+                * The contents of the buffer are garbage.  Shouldn't happen,
+                * and this read is likely to fail, but might as well try.
+                */
+               if (F_ISSET(bhp, BH_TRASH))
+                       goto reread;
+
+               /*
+                * BH_CALLPGIN --
+                * The buffer was converted so it could be written, and the
+                * contents need to be converted again.
+                */
+               if (F_ISSET(bhp, BH_CALLPGIN)) {
+                       if ((ret = __memp_pg(dbmfp, bhp, 1)) != 0)
+                               goto err;
+                       F_CLR(bhp, BH_CALLPGIN);
+               }
+
+               ++mp->stat.st_cache_hit;
+               ++mfp->stat.st_cache_hit;
+               *(void **)addrp = bhp->buf;
+               goto done;
        }
 
-alloc: /*
-        * Allocate a new buffer header and data space, and mark the contents
-        * as useless.
-        */
+alloc: /* Allocate new buffer header and data space. */
        if ((ret = __memp_ralloc(dbmp, sizeof(BH) -
            sizeof(u_int8_t) + mfp->stat.st_pagesize, NULL, &bhp)) != 0)
                goto err;
-       addr = bhp->buf;
-#ifdef DEBUG
-       if ((ALIGNTYPE)addr & (sizeof(size_t) - 1)) {
+
+#ifdef DIAGNOSTIC
+       if ((ALIGNTYPE)bhp->buf & (sizeof(size_t) - 1)) {
                __db_err(dbmp->dbenv,
                    "Internal error: BH data NOT size_t aligned.");
-               abort();
+               ret = EINVAL;
+               goto err;
        }
 #endif
+       /* Initialize the BH fields. */
        memset(bhp, 0, sizeof(BH));
        LOCKINIT(dbmp, &bhp->mutex);
+       bhp->ref = 1;
+       bhp->pgno = *pgnoaddr;
+       bhp->mf_offset = mf_offset;
 
        /*
         * Prepend the bucket header to the head of the appropriate MPOOL
         * bucket hash list.  Append the bucket header to the tail of the
         * MPOOL LRU chain.
-        *
-        * We have to do this before we read in the page so we can discard
-        * our region lock without screwing up the world.
         */
-       bucket = BUCKET(mp, mf_offset, *pgnoaddr);
        SH_TAILQ_INSERT_HEAD(&dbmp->htab[bucket], bhp, hq, __bh);
        SH_TAILQ_INSERT_TAIL(&mp->bhq, bhp, q);
-       ++mp->stat.st_page_clean;
-       b_inserted = 1;
-
-       /* Set the page number, and associated MPOOLFILE. */
-       bhp->mf_offset = mf_offset;
-       bhp->pgno = *pgnoaddr;
 
        /*
-        * If we know we created the page, zero it out and continue.
+        * If we created the page, zero it out and continue.
         *
         * !!!
-        * Note: DB_MPOOL_NEW deliberately doesn't call the pgin function.
+        * Note: DB_MPOOL_NEW specifically doesn't call the pgin function.
         * If DB_MPOOL_CREATE is used, then the application's pgin function
         * has to be able to handle pages of 0's -- if it uses DB_MPOOL_NEW,
         * it can detect all of its page creates, and not bother.
         *
         * Otherwise, read the page into memory, optionally creating it if
         * DB_MPOOL_CREATE is set.
-        *
-        * Increment the reference count for created buffers, but importantly,
-        * increment the reference count for buffers we're about to read so
-        * that the buffer can't move.
         */
-       ++bhp->ref;
-       b_incr = 1;
+       if (LF_ISSET(DB_MPOOL_NEW)) {
+               if (mfp->clear_len == 0)
+                       memset(bhp->buf, 0, mfp->stat.st_pagesize);
+               else {
+                       memset(bhp->buf, 0, mfp->clear_len);
+#ifdef DIAGNOSTIC
+                       memset(bhp->buf + mfp->clear_len, 0xff,
+                           mfp->stat.st_pagesize - mfp->clear_len);
+#endif
+               }
 
-       if (LF_ISSET(DB_MPOOL_NEW))
-               memset(addr, 0, mfp->stat.st_pagesize);
-       else {
+               ++mp->stat.st_page_create;
+               ++mfp->stat.st_page_create;
+       else {
                /*
                 * It's possible for the read function to fail, which means
-                * that we fail as well.
+                * that we fail as well.  Note, the __memp_pgread() function
+                * discards the region lock, so the buffer must be pinned
+                * down so that it cannot move and its contents are unchanged.
                 */
 reread:                if ((ret = __memp_pgread(dbmfp,
-                   bhp, LF_ISSET(DB_MPOOL_CREATE | DB_MPOOL_NEW))) != 0)
-                       goto err;
-
-               /*
-                * !!!
-                * The __memp_pgread call discarded and reacquired the region
-                * lock.  Because the buffer reference count was incremented
-                * before the region lock was discarded the buffer can't move
-                * and its contents can't change.
-                */
-               ++mp->stat.st_cache_miss;
-               ++mfp->stat.st_cache_miss;
-       }
-
-       if (0) {
-found:         /* Increment the reference count. */
-               if (bhp->ref == UINT16_T_MAX) {
-                       __db_err(dbmp->dbenv,
-                           "%s: too many references to page %lu",
-                           __memp_fn(dbmfp), bhp->pgno);
-                       ret = EINVAL;
-                       goto err;
-               }
-               ++bhp->ref;
-               b_incr = 1;
-
-               /*
-                * Any found buffer might be trouble.
-                *
-                * BH_LOCKED --
-                * I/O in progress, wait for it to finish.  Because the buffer
-                * reference count was incremented before the region lock was
-                * discarded we know the buffer can't move and its contents
-                * can't change.
-                */
-               for (cnt = 0; F_ISSET(bhp, BH_LOCKED); ++cnt) {
-                       UNLOCKREGION(dbmp);
-
+                   bhp, LF_ISSET(DB_MPOOL_CREATE))) != 0) {
                        /*
-                        * Sleep so that we don't simply spin, switching locks.
-                        * (See the comment in include/mp.h.)
+                        * !!!
+                        * Discard the buffer unless another thread is waiting
+                        * on our I/O to complete.  Regardless, the header has
+                        * the BH_TRASH flag set.
                         */
-                       if (cnt != 0 &&
-                           (__db_yield == NULL || __db_yield() != 0))
-                               __db_sleep(0, 1);
-
-                       LOCKBUFFER(dbmp, bhp);
-                       /* Waiting for I/O to finish... */
-                       UNLOCKBUFFER(dbmp, bhp);
-                       LOCKREGION(dbmp);
-               }
-
-               /*
-                * BH_TRASH --
-                * The buffer is garbage.
-                */
-               if (F_ISSET(bhp, BH_TRASH))
-                       goto reread;
-
-               /*
-                * BH_CALLPGIN --
-                * The buffer was written, and the contents need to be
-                * converted again.
-                */
-               if (F_ISSET(bhp, BH_CALLPGIN)) {
-                       if ((ret = __memp_pg(dbmfp, bhp, 1)) != 0)
-                               goto err;
-                       F_CLR(bhp, BH_CALLPGIN);
+                       if (bhp->ref == 1)
+                               __memp_bhfree(dbmp, mfp, bhp, 1);
+                       goto err;
                }
 
-               ++mp->stat.st_cache_hit;
-               ++mfp->stat.st_cache_hit;
+               ++mp->stat.st_cache_miss;
+               ++mfp->stat.st_cache_miss;
        }
 
        /*
@@ -319,23 +323,30 @@ found:            /* Increment the reference count. */
        if (bhp->pgno > mfp->last_pgno)
                mfp->last_pgno = bhp->pgno;
 
-mapret:        LOCKHANDLE(dbmp, dbmfp->mutexp);
+       ++mp->stat.st_page_clean;
+       *(void **)addrp = bhp->buf;
+
+done:  /* Update the chain search statistics. */
+       if (st_hsearch) {
+               ++mp->stat.st_hash_searches;
+               if (st_hsearch > mp->stat.st_hash_longest)
+                       mp->stat.st_hash_longest = st_hsearch;
+               mp->stat.st_hash_examined += st_hsearch;
+       }
+
+       UNLOCKREGION(dbmp);
+
+       LOCKHANDLE(dbmp, dbmfp->mutexp);
        ++dbmfp->pinref;
        UNLOCKHANDLE(dbmp, dbmfp->mutexp);
 
-       if (0) {
-err:           /*
-                * If no other process is already waiting on a created buffer,
-                * go ahead and discard it, it's not useful.
-                */
-               if (b_incr)
-                       --bhp->ref;
-               if (b_inserted && bhp->ref == 0)
-                       __memp_bhfree(dbmp, mfp, bhp, 1);
-       }
+       return (0);
 
+err:   /* Discard our reference. */
+       if (b_incr)
+               --bhp->ref;
        UNLOCKREGION(dbmp);
 
-       *(void **)addrp = addr;
+       *(void **)addrp = NULL;
        return (ret);
 }
index 0f41122..a4cbac8 100644 (file)
@@ -1,24 +1,20 @@
 /*-
  * See the file LICENSE for redistribution information.
  *
- * Copyright (c) 1996, 1997
+ * Copyright (c) 1996, 1997, 1998
  *     Sleepycat Software.  All rights reserved.
  */
 #include "config.h"
 
 #ifndef lint
-static const char sccsid[] = "@(#)mp_fopen.c   10.37 (Sleepycat) 1/18/98";
+static const char sccsid[] = "@(#)mp_fopen.c   10.47 (Sleepycat) 5/4/98";
 #endif /* not lint */
 
 #ifndef NO_SYSTEM_INCLUDES
 #include <sys/types.h>
-#include <sys/mman.h>
-#include <sys/stat.h>
 
 #include <errno.h>
-#include <stdlib.h>
 #include <string.h>
-#include <unistd.h>
 #endif
 
 #include "db_int.h"
@@ -28,22 +24,21 @@ static const char sccsid[] = "@(#)mp_fopen.c        10.37 (Sleepycat) 1/18/98";
 #include "common_ext.h"
 
 static int __memp_mf_close __P((DB_MPOOL *, DB_MPOOLFILE *));
-static int __memp_mf_open __P((DB_MPOOL *, const char *,
-    int, size_t, db_pgno_t, int, DBT *, u_int8_t *, MPOOLFILE **));
+static int __memp_mf_open __P((DB_MPOOL *,
+    const char *, size_t, db_pgno_t, DB_MPOOL_FINFO *, MPOOLFILE **));
 
 /*
  * memp_fopen --
  *     Open a backing file for the memory pool.
  */
 int
-memp_fopen(dbmp, path, ftype,
-    flags, mode, pagesize, lsn_offset, pgcookie, fileid, retp)
+memp_fopen(dbmp, path, flags, mode, pagesize, finfop, retp)
        DB_MPOOL *dbmp;
        const char *path;
-       int ftype, flags, mode, lsn_offset;
+       u_int32_t flags;
+       int mode;
        size_t pagesize;
-       DBT *pgcookie;
-       u_int8_t *fileid;
+       DB_MPOOL_FINFO *finfop;
        DB_MPOOLFILE **retp;
 {
        int ret;
@@ -59,31 +54,31 @@ memp_fopen(dbmp, path, ftype,
                return (EINVAL);
        }
 
-       return (__memp_fopen(dbmp, NULL, path, ftype,
-           flags, mode, pagesize, lsn_offset, pgcookie, fileid, 1, retp));
+       return (__memp_fopen(dbmp,
+           NULL, path, flags, mode, pagesize, 1, finfop, retp));
 }
 
 /*
  * __memp_fopen --
  *     Open a backing file for the memory pool; internal version.
  *
- * PUBLIC: int __memp_fopen __P((DB_MPOOL *, MPOOLFILE *, const char *, int,
- * PUBLIC:    int, int, size_t, int, DBT *, u_int8_t *, int, DB_MPOOLFILE **));
+ * PUBLIC: int __memp_fopen __P((DB_MPOOL *, MPOOLFILE *, const char *,
+ * PUBLIC:    u_int32_t, int, size_t, int, DB_MPOOL_FINFO *, DB_MPOOLFILE **));
  */
 int
-__memp_fopen(dbmp, mfp, path,
-    ftype, flags, mode, pagesize, lsn_offset, pgcookie, fileid, needlock, retp)
+__memp_fopen(dbmp, mfp, path, flags, mode, pagesize, needlock, finfop, retp)
        DB_MPOOL *dbmp;
        MPOOLFILE *mfp;
        const char *path;
-       int ftype, flags, mode, lsn_offset, needlock;
+       u_int32_t flags;
+       int mode, needlock;
        size_t pagesize;
-       DBT *pgcookie;
-       u_int8_t *fileid;
+       DB_MPOOL_FINFO *finfop;
        DB_MPOOLFILE **retp;
 {
        DB_ENV *dbenv;
        DB_MPOOLFILE *dbmfp;
+       DB_MPOOL_FINFO finfo;
        db_pgno_t last_pgno;
        size_t size;
        u_int32_t mbytes, bytes;
@@ -91,18 +86,34 @@ __memp_fopen(dbmp, mfp, path,
        u_int8_t idbuf[DB_FILE_ID_LEN];
        char *rpath;
 
-       /*
-        * XXX
-        * If mfp is provided, the following arguments do NOT need to be
-        * specified:
-        *      lsn_offset
-        *      pgcookie
-        *      fileid
-        */
        dbenv = dbmp->dbenv;
        ret = 0;
        rpath = NULL;
 
+       /*
+        * If mfp is provided, we take the DB_MPOOL_FINFO information from
+        * the mfp.  We don't bother initializing everything, because some
+        * of them are expensive to acquire.  If no mfp is provided and the
+        * finfop argument is NULL, we default the values.
+        */
+       if (finfop == NULL) {
+               memset(&finfo, 0, sizeof(finfo));
+               if (mfp != NULL) {
+                       finfo.ftype = mfp->ftype;
+                       finfo.pgcookie = NULL;
+                       finfo.fileid = NULL;
+                       finfo.lsn_offset = mfp->lsn_off;
+                       finfo.clear_len = mfp->clear_len;
+               } else {
+                       finfo.ftype = 0;
+                       finfo.pgcookie = NULL;
+                       finfo.fileid = NULL;
+                       finfo.lsn_offset = -1;
+                       finfo.clear_len = 0;
+               }
+               finfop = &finfo;
+       }
+
        /* Allocate and initialize the per-process structure. */
        if ((dbmfp =
            (DB_MPOOLFILE *)__db_calloc(1, sizeof(DB_MPOOLFILE))) == NULL) {
@@ -126,11 +137,11 @@ __memp_fopen(dbmp, mfp, path,
        } else {
                /* Get the real name for this file and open it. */
                if ((ret = __db_appname(dbenv,
-                   DB_APP_DATA, NULL, path, NULL, &rpath)) != 0)
+                   DB_APP_DATA, NULL, path, 0, NULL, &rpath)) != 0)
                        goto err;
                if ((ret = __db_open(rpath,
-                   LF_ISSET(DB_CREATE | DB_RDONLY), DB_CREATE | DB_RDONLY,
-                   mode, &dbmfp->fd)) != 0) {
+                  LF_ISSET(DB_CREATE | DB_RDONLY),
+                  DB_CREATE | DB_RDONLY, mode, &dbmfp->fd)) != 0) {
                        __db_err(dbenv, "%s: %s", rpath, strerror(ret));
                        goto err;
                }
@@ -156,12 +167,11 @@ __memp_fopen(dbmp, mfp, path,
                 * don't use timestamps, otherwise there'd be no chance of any
                 * other process joining the party.
                 */
-               if (mfp == NULL && fileid == NULL) {
+               if (finfop->fileid == NULL) {
                        if ((ret = __db_fileid(dbenv, rpath, 0, idbuf)) != 0)
                                goto err;
-                       fileid = idbuf;
+                       finfop->fileid = idbuf;
                }
-               FREES(rpath);
        }
 
        /*
@@ -173,8 +183,8 @@ __memp_fopen(dbmp, mfp, path,
                LOCKREGION(dbmp);
 
        if (mfp == NULL)
-               ret = __memp_mf_open(dbmp, path, ftype,
-                   pagesize, last_pgno, lsn_offset, pgcookie, fileid, &mfp);
+               ret = __memp_mf_open(dbmp,
+                   path, pagesize, last_pgno, finfop, &mfp);
        else {
                ++mfp->ref;
                ret = 0;
@@ -218,7 +228,7 @@ __memp_fopen(dbmp, mfp, path,
                        F_CLR(mfp, MP_CAN_MMAP);
                if (path == NULL)
                        F_CLR(mfp, MP_CAN_MMAP);
-               if (ftype != 0)
+               if (finfop->ftype != 0)
                        F_CLR(mfp, MP_CAN_MMAP);
                if (LF_ISSET(DB_NOMMAP))
                        F_CLR(mfp, MP_CAN_MMAP);
@@ -229,11 +239,14 @@ __memp_fopen(dbmp, mfp, path,
        dbmfp->addr = NULL;
        if (F_ISSET(mfp, MP_CAN_MMAP)) {
                dbmfp->len = size;
-               if (__db_map(dbmfp->fd, dbmfp->len, 1, 1, &dbmfp->addr) != 0) {
+               if (__db_mapfile(rpath,
+                   dbmfp->fd, dbmfp->len, 1, &dbmfp->addr) != 0) {
                        dbmfp->addr = NULL;
                        F_CLR(mfp, MP_CAN_MMAP);
                }
        }
+       if (rpath != NULL)
+               FREES(rpath);
 
        LOCKHANDLE(dbmp, dbmp->mutexp);
        TAILQ_INSERT_TAIL(&dbmp->dbmfq, dbmfp, q);
@@ -260,15 +273,12 @@ err:      /*
  *     Open an MPOOLFILE.
  */
 static int
-__memp_mf_open(dbmp, path,
-    ftype, pagesize, last_pgno, lsn_offset, pgcookie, fileid, retp)
+__memp_mf_open(dbmp, path, pagesize, last_pgno, finfop, retp)
        DB_MPOOL *dbmp;
        const char *path;
-       int ftype, lsn_offset;
        size_t pagesize;
        db_pgno_t last_pgno;
-       DBT *pgcookie;
-       u_int8_t *fileid;
+       DB_MPOOL_FINFO *finfop;
        MPOOLFILE **retp;
 {
        MPOOLFILE *mfp;
@@ -286,12 +296,13 @@ __memp_mf_open(dbmp, path,
                    mfp != NULL; mfp = SH_TAILQ_NEXT(mfp, q, __mpoolfile)) {
                        if (F_ISSET(mfp, MP_TEMP))
                                continue;
-                       if (!memcmp(fileid,
+                       if (!memcmp(finfop->fileid,
                            R_ADDR(dbmp, mfp->fileid_off), DB_FILE_ID_LEN)) {
-                               if (ftype != mfp->ftype ||
+                               if (finfop->clear_len != mfp->clear_len ||
+                                   finfop->ftype != mfp->ftype ||
                                    pagesize != mfp->stat.st_pagesize) {
                                        __db_err(dbmp->dbenv,
-                                           "%s: ftype or pagesize changed",
+                           "%s: ftype, clear length or pagesize changed",
                                            path);
                                        return (EINVAL);
                                }
@@ -311,8 +322,9 @@ __memp_mf_open(dbmp, path,
        /* Initialize the structure. */
        memset(mfp, 0, sizeof(MPOOLFILE));
        mfp->ref = 1;
-       mfp->ftype = ftype;
-       mfp->lsn_off = lsn_offset;
+       mfp->ftype = finfop->ftype;
+       mfp->lsn_off = finfop->lsn_offset;
+       mfp->clear_len = finfop->clear_len;
 
        /*
         * If the user specifies DB_MPOOL_LAST or DB_MPOOL_NEW on a memp_fget,
@@ -320,7 +332,7 @@ __memp_mf_open(dbmp, path,
         * it away.
         */
        mfp->stat.st_pagesize = pagesize;
-       mfp->last_pgno = last_pgno;
+       mfp->orig_last_pgno = mfp->last_pgno = last_pgno;
 
        F_SET(mfp, MP_CAN_MMAP);
        if (ISTEMPORARY)
@@ -336,19 +348,19 @@ __memp_mf_open(dbmp, path,
                if ((ret = __memp_ralloc(dbmp,
                    DB_FILE_ID_LEN, &mfp->fileid_off, &p)) != 0)
                        goto err;
-               memcpy(p, fileid, DB_FILE_ID_LEN);
+               memcpy(p, finfop->fileid, DB_FILE_ID_LEN);
        }
 
        /* Copy the page cookie into shared memory. */
-       if (pgcookie == NULL || pgcookie->size == 0) {
+       if (finfop->pgcookie == NULL || finfop->pgcookie->size == 0) {
                mfp->pgcookie_len = 0;
                mfp->pgcookie_off = 0;
        } else {
                if ((ret = __memp_ralloc(dbmp,
-                   pgcookie->size, &mfp->pgcookie_off, &p)) != 0)
+                   finfop->pgcookie->size, &mfp->pgcookie_off, &p)) != 0)
                        goto err;
-               memcpy(p, pgcookie->data, pgcookie->size);
-               mfp->pgcookie_len = pgcookie->size;
+               memcpy(p, finfop->pgcookie->data, finfop->pgcookie->size);
+               mfp->pgcookie_len = finfop->pgcookie->size;
        }
 
        /* Prepend the MPOOLFILE to the list of MPOOLFILE's. */
@@ -397,7 +409,7 @@ memp_fclose(dbmfp)
 
        /* Discard any mmap information. */
        if (dbmfp->addr != NULL &&
-           (ret = __db_unmap(dbmfp->addr, dbmfp->len)) != 0)
+           (ret = __db_unmapfile(dbmfp->addr, dbmfp->len)) != 0)
                __db_err(dbmp->dbenv,
                    "%s: %s", __memp_fn(dbmfp), strerror(ret));
 
@@ -480,13 +492,13 @@ __memp_mf_close(dbmp, dbmfp)
        SH_TAILQ_REMOVE(&mp->mpfq, mfp, q, __mpoolfile);
 
        /* Free the space. */
-       __db_shalloc_free(dbmp->addr, mfp);
        if (mfp->path_off != 0)
                __db_shalloc_free(dbmp->addr, R_ADDR(dbmp, mfp->path_off));
        if (mfp->fileid_off != 0)
                __db_shalloc_free(dbmp->addr, R_ADDR(dbmp, mfp->fileid_off));
        if (mfp->pgcookie_off != 0)
                __db_shalloc_free(dbmp->addr, R_ADDR(dbmp, mfp->pgcookie_off));
+       __db_shalloc_free(dbmp->addr, mfp);
 
 ret1:  UNLOCKREGION(dbmp);
        return (0);
index 335ee9f..5675493 100644 (file)
@@ -1,20 +1,19 @@
 /*-
  * See the file LICENSE for redistribution information.
  *
- * Copyright (c) 1996, 1997
+ * Copyright (c) 1996, 1997, 1998
  *     Sleepycat Software.  All rights reserved.
  */
 #include "config.h"
 
 #ifndef lint
-static const char sccsid[] = "@(#)mp_fput.c    10.17 (Sleepycat) 12/20/97";
+static const char sccsid[] = "@(#)mp_fput.c    10.22 (Sleepycat) 4/26/98";
 #endif /* not lint */
 
 #ifndef NO_SYSTEM_INCLUDES
 #include <sys/types.h>
 
 #include <errno.h>
-#include <stdlib.h>
 #endif
 
 #include "db_int.h"
@@ -31,12 +30,11 @@ int
 memp_fput(dbmfp, pgaddr, flags)
        DB_MPOOLFILE *dbmfp;
        void *pgaddr;
-       int flags;
+       u_int32_t flags;
 {
        BH *bhp;
        DB_MPOOL *dbmp;
        MPOOL *mp;
-       MPOOLFILE *mfp;
        int wrote, ret;
 
        dbmp = dbmfp->dbmp;
@@ -71,8 +69,9 @@ memp_fput(dbmfp, pgaddr, flags)
 
        /*
         * If we're mapping the file, there's nothing to do.  Because we can
-        * quit mapping at any time, we have to check on each buffer to see
-        * if it's in the map region.
+        * stop mapping the file at any time, we have to check on each buffer
+        * to see if the address we gave the application was part of the map
+        * region.
         */
        if (dbmfp->addr != NULL && pgaddr >= dbmfp->addr &&
            (u_int8_t *)pgaddr <= (u_int8_t *)dbmfp->addr + dbmfp->len)
@@ -98,36 +97,33 @@ memp_fput(dbmfp, pgaddr, flags)
                F_SET(bhp, BH_DISCARD);
 
        /*
-        * If more than one reference to the page, we're done.  Ignore discard
-        * flags (for now) and leave it at its position in the LRU chain.  The
-        * rest gets done at last reference close.
+        * Check for a reference count going to zero.  This can happen if the
+        * application returns a page twice.
         */
-#ifdef DEBUG
        if (bhp->ref == 0) {
-               __db_err(dbmp->dbenv,
-    "Unpinned page returned: reference count on page %lu went negative.",
-                   (u_long)bhp->pgno);
-               abort();
+               __db_err(dbmp->dbenv, "%s: page %lu: unpinned page returned",
+                   __memp_fn(dbmfp), (u_long)bhp->pgno);
+               UNLOCKREGION(dbmp);
+               return (EINVAL);
        }
-#endif
+
+       /*
+        * If more than one reference to the page, we're done.  Ignore the
+        * discard flags (for now) and leave it at its position in the LRU
+        * chain.  The rest gets done at last reference close.
+        */
        if (--bhp->ref > 0) {
                UNLOCKREGION(dbmp);
                return (0);
        }
 
-       /* Move the buffer to the head/tail of the LRU chain. */
-       SH_TAILQ_REMOVE(&mp->bhq, bhp, q, __bh);
-       if (F_ISSET(bhp, BH_DISCARD))
-               SH_TAILQ_INSERT_HEAD(&mp->bhq, bhp, q, __bh);
-       else
-               SH_TAILQ_INSERT_TAIL(&mp->bhq, bhp, q);
-
        /*
-        * If this buffer is scheduled for writing because of a checkpoint,
-        * write it now.  If we can't write it, set a flag so that the next
-        * time the memp_sync function is called we try writing it there,
-        * as the checkpoint application better be able to write all of the
-        * files.
+        * If this buffer is scheduled for writing because of a checkpoint, we
+        * need to write it (if we marked it dirty), or update the checkpoint
+        * counters (if we didn't mark it dirty).  If we try to write it and
+        * can't, that's not necessarily an error, but set a flag so that the
+        * next time the memp_sync function runs we try writing it there, as
+        * the checkpoint application better be able to write all of the files.
         */
        if (F_ISSET(bhp, BH_WRITE))
                if (F_ISSET(bhp, BH_DIRTY)) {
@@ -137,12 +133,18 @@ memp_fput(dbmfp, pgaddr, flags)
                } else {
                        F_CLR(bhp, BH_WRITE);
 
-                       mfp = R_ADDR(dbmp, bhp->mf_offset);
-                       --mfp->lsn_cnt;
-
+                       --dbmfp->mfp->lsn_cnt;
                        --mp->lsn_cnt;
                }
 
+       /* Move the buffer to the head/tail of the LRU chain. */
+       SH_TAILQ_REMOVE(&mp->bhq, bhp, q, __bh);
+       if (F_ISSET(bhp, BH_DISCARD))
+               SH_TAILQ_INSERT_HEAD(&mp->bhq, bhp, q, __bh);
+       else
+               SH_TAILQ_INSERT_TAIL(&mp->bhq, bhp, q);
+
+
        UNLOCKREGION(dbmp);
        return (0);
 }
index 2eff7dd..3b352aa 100644 (file)
@@ -1,13 +1,13 @@
 /*-
  * See the file LICENSE for redistribution information.
  *
- * Copyright (c) 1996, 1997
+ * Copyright (c) 1996, 1997, 1998
  *     Sleepycat Software.  All rights reserved.
  */
 #include "config.h"
 
 #ifndef lint
-static const char sccsid[] = "@(#)mp_fset.c    10.12 (Sleepycat) 11/26/97";
+static const char sccsid[] = "@(#)mp_fset.c    10.15 (Sleepycat) 4/26/98";
 #endif /* not lint */
 
 #ifndef NO_SYSTEM_INCLUDES
@@ -30,16 +30,14 @@ int
 memp_fset(dbmfp, pgaddr, flags)
        DB_MPOOLFILE *dbmfp;
        void *pgaddr;
-       int flags;
+       u_int32_t flags;
 {
        BH *bhp;
        DB_MPOOL *dbmp;
        MPOOL *mp;
-       MPOOLFILE *mfp;
        int ret;
 
        dbmp = dbmfp->dbmp;
-       mfp = dbmfp->mfp;
        mp = dbmp->mp;
 
        /* Validate arguments. */
index ca81f8d..fc985bc 100644 (file)
@@ -1,23 +1,20 @@
 /*-
  * See the file LICENSE for redistribution information.
  *
- * Copyright (c) 1996, 1997
+ * Copyright (c) 1996, 1997, 1998
  *     Sleepycat Software.  All rights reserved.
  */
 #include "config.h"
 
 #ifndef lint
-static const char sccsid[] = "@(#)mp_open.c    10.16 (Sleepycat) 11/28/97";
+static const char sccsid[] = "@(#)mp_open.c    10.23 (Sleepycat) 5/3/98";
 #endif /* not lint */
 
 #ifndef NO_SYSTEM_INCLUDES
 #include <sys/types.h>
 
 #include <errno.h>
-#include <fcntl.h>
-#include <stdlib.h>
 #include <string.h>
-#include <unistd.h>
 #endif
 
 #include "db_int.h"
@@ -33,13 +30,14 @@ static const char sccsid[] = "@(#)mp_open.c 10.16 (Sleepycat) 11/28/97";
 int
 memp_open(path, flags, mode, dbenv, retp)
        const char *path;
-       int flags, mode;
+       u_int32_t flags;
+       int mode;
        DB_ENV *dbenv;
        DB_MPOOL **retp;
 {
        DB_MPOOL *dbmp;
        size_t cachesize;
-       int ret;
+       int is_private, ret;
 
        /* Validate arguments. */
 #ifdef HAVE_SPINLOCKS
@@ -62,15 +60,16 @@ memp_open(path, flags, mode, dbenv, retp)
        dbmp->dbenv = dbenv;
 
        /* Decide if it's possible for anyone else to access the pool. */
-       if ((dbenv == NULL && path == NULL) || LF_ISSET(DB_MPOOL_PRIVATE))
-               F_SET(dbmp, MP_ISPRIVATE);
+       is_private =
+           (dbenv == NULL && path == NULL) || LF_ISSET(DB_MPOOL_PRIVATE);
 
        /*
         * Map in the region.  We do locking regardless, as portions of it are
         * implemented in common code (if we put the region in a file, that is).
         */
        F_SET(dbmp, MP_LOCKREGION);
-       if ((ret = __memp_ropen(dbmp, path, cachesize, mode, flags)) != 0)
+       if ((ret = __memp_ropen(dbmp,
+           path, cachesize, mode, is_private, LF_ISSET(DB_CREATE))) != 0)
                goto err;
        F_CLR(dbmp, MP_LOCKREGION);
 
@@ -79,7 +78,7 @@ memp_open(path, flags, mode, dbenv, retp)
         * If it's threaded, then we have to lock both the handles and the
         * region, and we need to allocate a mutex for that purpose.
         */
-       if (!F_ISSET(dbmp, MP_ISPRIVATE))
+       if (!is_private)
                F_SET(dbmp, MP_LOCKREGION);
        if (LF_ISSET(DB_THREAD)) {
                F_SET(dbmp, MP_LOCKHANDLE | MP_LOCKREGION);
@@ -135,10 +134,11 @@ memp_close(dbmp)
        }
 
        /* Close the region. */
-       if ((t_ret = __memp_rclose(dbmp)) && ret == 0)
+       if ((t_ret = __db_rdetach(&dbmp->reginfo)) != 0 && ret == 0)
                ret = t_ret;
 
-       /* Discard the structure. */
+       if (dbmp->reginfo.path != NULL)
+               FREES(dbmp->reginfo.path);
        FREE(dbmp, sizeof(DB_MPOOL));
 
        return (ret);
@@ -154,8 +154,19 @@ memp_unlink(path, force, dbenv)
        int force;
        DB_ENV *dbenv;
 {
-       return (__db_runlink(dbenv,
-           DB_APP_NONE, path, DB_DEFAULT_MPOOL_FILE, force));
+       REGINFO reginfo;
+       int ret;
+
+       memset(&reginfo, 0, sizeof(reginfo));
+       reginfo.dbenv = dbenv;
+       reginfo.appname = DB_APP_NONE;
+       if (path != NULL && (reginfo.path = __db_strdup(path)) == NULL)
+               return (ENOMEM);
+       reginfo.file = DB_DEFAULT_MPOOL_FILE;
+       ret = __db_runlink(&reginfo, force);
+       if (reginfo.path != NULL)
+               FREES(reginfo.path);
+       return (ret);
 }
 
 /*
index 13a6c62..e83e0f4 100644 (file)
@@ -1,13 +1,13 @@
 /*-
  * See the file LICENSE for redistribution information.
  *
- * Copyright (c) 1996, 1997
+ * Copyright (c) 1996, 1997, 1998
  *     Sleepycat Software.  All rights reserved.
  */
 #include "config.h"
 
 #ifndef lint
-static const char sccsid[] = "@(#)mp_pr.c      10.21 (Sleepycat) 1/6/98";
+static const char sccsid[] = "@(#)mp_pr.c      10.26 (Sleepycat) 5/23/98";
 #endif /* not lint */
 
 #ifndef NO_SYSTEM_INCLUDES
@@ -15,20 +15,20 @@ static const char sccsid[] = "@(#)mp_pr.c   10.21 (Sleepycat) 1/6/98";
 
 #include <errno.h>
 #include <stdio.h>
-#include <stdlib.h>
 #include <string.h>
 #include <unistd.h>
 #endif
 
 #include "db_int.h"
+#include "db_page.h"
 #include "shqueue.h"
 #include "db_shash.h"
 #include "mp.h"
+#include "db_auto.h"
+#include "db_ext.h"
+#include "common_ext.h"
 
-static void __memp_pbh __P((FILE *, DB_MPOOL *, BH *, int));
-static void __memp_pdbmf __P((FILE *, DB_MPOOLFILE *, int));
-static void __memp_pmf __P((FILE *, MPOOLFILE *, int));
-static void __memp_pmp __P((FILE *, DB_MPOOL *, MPOOL *, int));
+static void __memp_pbh __P((DB_MPOOL *, BH *, size_t *, FILE *));
 
 /*
  * memp_stat --
@@ -64,6 +64,8 @@ memp_stat(dbmp, gspp, fspp, db_malloc)
                    dbmp->mp->rlayout.lock.mutex_set_wait;
                (*gspp)->st_region_nowait =
                    dbmp->mp->rlayout.lock.mutex_set_nowait;
+               (*gspp)->st_refcnt = dbmp->mp->rlayout.refcnt;
+               (*gspp)->st_regsize = dbmp->mp->rlayout.size;
 
                UNLOCKREGION(dbmp);
        }
@@ -77,7 +79,8 @@ memp_stat(dbmp, gspp, fspp, db_malloc)
                for (len = 0,
                    mfp = SH_TAILQ_FIRST(&dbmp->mp->mpfq, __mpoolfile);
                    mfp != NULL;
-                   ++len, mfp = SH_TAILQ_NEXT(mfp, q, __mpoolfile));
+                   ++len, mfp = SH_TAILQ_NEXT(mfp, q, __mpoolfile))
+                       ;
 
                UNLOCKREGION(dbmp);
 
@@ -148,174 +151,118 @@ __memp_fns(dbmp, mfp)
        return ((char *)R_ADDR(dbmp, mfp->path_off));
 }
 
+#define        FMAP_ENTRIES    200                     /* Files we map. */
+
+#define        MPOOL_DUMP_HASH 0x01                    /* Debug hash chains. */
+#define        MPOOL_DUMP_LRU  0x02                    /* Debug LRU chains. */
+#define        MPOOL_DUMP_MEM  0x04                    /* Debug region memory. */
+#define        MPOOL_DUMP_ALL  0x07                    /* Debug all. */
+
+
 /*
- * __memp_debug --
+ * __memp_dump_region --
  *     Display MPOOL structures.
  *
- * PUBLIC: void __memp_debug __P((DB_MPOOL *, FILE *, int));
+ * PUBLIC: void __memp_dump_region __P((DB_MPOOL *, char *, FILE *));
  */
 void
-__memp_debug(dbmp, fp, data)
+__memp_dump_region(dbmp, area, fp)
        DB_MPOOL *dbmp;
+       char *area;
        FILE *fp;
-       int data;
 {
+       BH *bhp;
+       DB_HASHTAB *htabp;
        DB_MPOOLFILE *dbmfp;
-       u_long cnt;
+       MPOOL *mp;
+       MPOOLFILE *mfp;
+       size_t bucket, fmap[FMAP_ENTRIES + 1];
+       u_int32_t flags;
+       int cnt;
 
        /* Make it easy to call from the debugger. */
        if (fp == NULL)
                fp = stderr;
 
-       /* Welcome message. */
-       (void)fprintf(fp, "%s\nMpool per-process (%lu) statistics\n",
-           DB_LINE, (u_long)getpid());
-
-       if (data)
-               (void)fprintf(fp, "    fd: %d; addr %lx; maddr %lx\n",
-                   dbmp->fd, (u_long)dbmp->addr, (u_long)dbmp->maddr);
-
-       /* Display the DB_MPOOLFILE structures. */
-       for (cnt = 0, dbmfp = TAILQ_FIRST(&dbmp->dbmfq);
-           dbmfp != NULL; ++cnt, dbmfp = TAILQ_NEXT(dbmfp, q));
-       (void)fprintf(fp, "%lu process-local files\n", cnt);
-       for (dbmfp = TAILQ_FIRST(&dbmp->dbmfq);
-           dbmfp != NULL; dbmfp = TAILQ_NEXT(dbmfp, q)) {
-               (void)fprintf(fp, "%s\n", __memp_fn(dbmfp));
-               __memp_pdbmf(fp, dbmfp, data);
-       }
+       for (flags = 0; *area != '\0'; ++area)
+               switch (*area) {
+               case 'A':
+                       LF_SET(MPOOL_DUMP_ALL);
+                       break;
+               case 'h':
+                       LF_SET(MPOOL_DUMP_HASH);
+                       break;
+               case 'l':
+                       LF_SET(MPOOL_DUMP_LRU);
+                       break;
+               case 'm':
+                       LF_SET(MPOOL_DUMP_MEM);
+                       break;
+               }
 
-       /* Switch to global statistics. */
-       (void)fprintf(fp, "\n%s\nMpool statistics\n", DB_LINE);
+       LOCKREGION(dbmp);
 
-       /* Display the MPOOL structure. */
-       __memp_pmp(fp, dbmp, dbmp->mp, data);
+       mp = dbmp->mp;
 
-       /* Flush in case we're debugging. */
-       (void)fflush(fp);
-}
-
-/*
- * __memp_pdbmf --
- *     Display a DB_MPOOLFILE structure.
- */
-static void
-__memp_pdbmf(fp, dbmfp, data)
-       FILE *fp;
-       DB_MPOOLFILE *dbmfp;
-       int data;
-{
-       if (!data)
-               return;
-
-       (void)fprintf(fp, "    fd: %d; %s\n",
-           dbmfp->fd, F_ISSET(dbmfp, MP_READONLY) ? "readonly" : "read/write");
-}
-
-/*
- * __memp_pmp --
- *     Display the MPOOL structure.
- */
-static void
-__memp_pmp(fp, dbmp, mp, data)
-       FILE *fp;
-       DB_MPOOL *dbmp;
-       MPOOL *mp;
-       int data;
-{
-       BH *bhp;
-       MPOOLFILE *mfp;
-       DB_HASHTAB *htabp;
-       size_t bucket;
-       int cnt;
-       const char *sep;
-
-       (void)fprintf(fp, "references: %lu; cachesize: %lu\n",
-           (u_long)mp->rlayout.refcnt, (u_long)mp->stat.st_cachesize);
-       (void)fprintf(fp,
-           "    %lu pages created\n", (u_long)mp->stat.st_page_create);
-       (void)fprintf(fp,
-           "    %lu mmap pages returned\n", (u_long)mp->stat.st_map);
-       (void)fprintf(fp, "    %lu I/O's (%lu read, %lu written)\n",
-           (u_long)mp->stat.st_page_in + mp->stat.st_page_out,
-           (u_long)mp->stat.st_page_in, (u_long)mp->stat.st_page_out);
-       if (mp->stat.st_cache_hit + mp->stat.st_cache_miss != 0)
-               (void)fprintf(fp,
-                   "    %.0f%% cache hit rate (%lu hit, %lu miss)\n",
-                   ((double)mp->stat.st_cache_hit /
-           (mp->stat.st_cache_hit + mp->stat.st_cache_miss)) * 100,
-                   (u_long)mp->stat.st_cache_hit,
-                   (u_long)mp->stat.st_cache_miss);
+       /* Display MPOOL structures. */
+       (void)fprintf(fp, "%s\nPool (region addr 0x%lx, alloc addr 0x%lx)\n",
+           DB_LINE, (u_long)dbmp->reginfo.addr, (u_long)dbmp->addr);
 
        /* Display the MPOOLFILE structures. */
-       for (cnt = 0, mfp = SH_TAILQ_FIRST(&dbmp->mp->mpfq, __mpoolfile);
-           mfp != NULL; ++cnt, mfp = SH_TAILQ_NEXT(mfp, q, __mpoolfile));
-       (void)fprintf(fp, "%d total files\n", cnt);
-       for (cnt = 1, mfp = SH_TAILQ_FIRST(&dbmp->mp->mpfq, __mpoolfile);
-           mfp != NULL; ++cnt, mfp = SH_TAILQ_NEXT(mfp, q, __mpoolfile)) {
-               (void)fprintf(fp, "file %d\n", cnt);
-               __memp_pmf(fp, mfp, data);
+       cnt = 0;
+       for (mfp = SH_TAILQ_FIRST(&dbmp->mp->mpfq, __mpoolfile);
+           mfp != NULL; mfp = SH_TAILQ_NEXT(mfp, q, __mpoolfile), ++cnt) {
+               (void)fprintf(fp, "file #%d: %s: %lu references: %s\n",
+                   cnt + 1, __memp_fns(dbmp, mfp), (u_long)mfp->ref,
+                   F_ISSET(mfp, MP_CAN_MMAP) ? "mmap" : "read/write");
+                   if (cnt < FMAP_ENTRIES)
+                       fmap[cnt] = R_OFFSET(dbmp, mfp);
        }
 
-       if (!data)
-               return;
+       for (dbmfp = TAILQ_FIRST(&dbmp->dbmfq);
+           dbmfp != NULL; dbmfp = TAILQ_NEXT(dbmfp, q), ++cnt) {
+               (void)fprintf(fp, "file #%d: %s: fd: %d: per-process, %s\n",
+                   cnt + 1, __memp_fn(dbmfp), dbmfp->fd,
+                   F_ISSET(dbmfp, MP_READONLY) ? "readonly" : "read/write");
+                   if (cnt < FMAP_ENTRIES)
+                       fmap[cnt] = R_OFFSET(dbmp, mfp);
+       }
+       if (cnt < FMAP_ENTRIES)
+               fmap[cnt] = INVALID;
+       else
+               fmap[FMAP_ENTRIES] = INVALID;
 
        /* Display the hash table list of BH's. */
-       (void)fprintf(fp, "%s\nHASH table of BH's (%lu buckets):\n",
-           DB_LINE, (u_long)mp->htab_buckets);
-       (void)fprintf(fp,
-           "longest chain searched %lu\n", (u_long)mp->stat.st_hash_longest);
-       (void)fprintf(fp, "average chain searched %lu (total/calls: %lu/%lu)\n",
-           (u_long)mp->stat.st_hash_examined /
-           (mp->stat.st_hash_searches ? mp->stat.st_hash_searches : 1),
-           (u_long)mp->stat.st_hash_examined,
-           (u_long)mp->stat.st_hash_searches);
-       for (htabp = dbmp->htab,
-           bucket = 0; bucket < mp->htab_buckets; ++htabp, ++bucket) {
-               if (SH_TAILQ_FIRST(&dbmp->htab[bucket], __bh) != NULL)
-                       (void)fprintf(fp, "%lu:\n", (u_long)bucket);
-               for (bhp = SH_TAILQ_FIRST(&dbmp->htab[bucket], __bh);
-                   bhp != NULL; bhp = SH_TAILQ_NEXT(bhp, hq, __bh))
-                       __memp_pbh(fp, dbmp, bhp, data);
+       if (LF_ISSET(MPOOL_DUMP_HASH)) {
+               (void)fprintf(fp,
+           "%s\nBH hash table (%lu hash slots)\npageno, file, ref, address\n",
+                   DB_LINE, (u_long)mp->htab_buckets);
+               for (htabp = dbmp->htab,
+                   bucket = 0; bucket < mp->htab_buckets; ++htabp, ++bucket) {
+                       if (SH_TAILQ_FIRST(&dbmp->htab[bucket], __bh) != NULL)
+                               (void)fprintf(fp, "%lu:\n", (u_long)bucket);
+                       for (bhp = SH_TAILQ_FIRST(&dbmp->htab[bucket], __bh);
+                           bhp != NULL; bhp = SH_TAILQ_NEXT(bhp, hq, __bh))
+                               __memp_pbh(dbmp, bhp, fmap, fp);
+               }
        }
 
        /* Display the LRU list of BH's. */
-       (void)fprintf(fp, "LRU list of BH's (pgno/offset):");
-       for (sep = "\n    ", bhp = SH_TAILQ_FIRST(&dbmp->mp->bhq, __bh);
-           bhp != NULL; sep = ", ", bhp = SH_TAILQ_NEXT(bhp, q, __bh))
-               (void)fprintf(fp, "%s%lu/%lu", sep,
-                   (u_long)bhp->pgno, (u_long)R_OFFSET(dbmp, bhp));
-       (void)fprintf(fp, "\n");
-}
+       if (LF_ISSET(MPOOL_DUMP_LRU)) {
+               (void)fprintf(fp, "%s\nBH LRU list\n", DB_LINE);
+               (void)fprintf(fp, "pageno, file, ref, address\n");
+               for (bhp = SH_TAILQ_FIRST(&dbmp->mp->bhq, __bh);
+                   bhp != NULL; bhp = SH_TAILQ_NEXT(bhp, q, __bh))
+                       __memp_pbh(dbmp, bhp, fmap, fp);
+       }
 
-/*
- * __memp_pmf --
- *     Display an MPOOLFILE structure.
- */
-static void
-__memp_pmf(fp, mfp, data)
-       FILE *fp;
-       MPOOLFILE *mfp;
-       int data;
-{
-       (void)fprintf(fp, "    %lu pages created\n",
-           (u_long)mfp->stat.st_page_create);
-       (void)fprintf(fp, "    %lu I/O's (%lu read, %lu written)\n",
-           (u_long)mfp->stat.st_page_in + mfp->stat.st_page_out,
-           (u_long)mfp->stat.st_page_in, (u_long)mfp->stat.st_page_out);
-       if (mfp->stat.st_cache_hit + mfp->stat.st_cache_miss != 0)
-               (void)fprintf(fp,
-                   "    %.0f%% cache hit rate (%lu hit, %lu miss)\n",
-                   ((double)mfp->stat.st_cache_hit /
-                   (mfp->stat.st_cache_hit + mfp->stat.st_cache_miss)) * 100,
-                   (u_long)mfp->stat.st_cache_hit,
-                   (u_long)mfp->stat.st_cache_miss);
-       if (!data)
-               return;
-
-       (void)fprintf(fp, "    %d references; %s; pagesize: %lu\n", mfp->ref,
-           F_ISSET(mfp, MP_CAN_MMAP) ? "mmap" : "read/write",
-           (u_long)mfp->stat.st_pagesize);
+       if (LF_ISSET(MPOOL_DUMP_MEM))
+               __db_shalloc_dump(dbmp->addr, fp);
+
+       UNLOCKREGION(dbmp);
+
+       /* Flush in case we're debugging. */
+       (void)fflush(fp);
 }
 
 /*
@@ -323,28 +270,37 @@ __memp_pmf(fp, mfp, data)
  *     Display a BH structure.
  */
 static void
-__memp_pbh(fp, dbmp, bhp, data)
-       FILE *fp;
+__memp_pbh(dbmp, bhp, fmap, fp)
        DB_MPOOL *dbmp;
        BH *bhp;
-       int data;
+       size_t *fmap;
+       FILE *fp;
 {
-       const char *sep;
-
-       if (!data)
-               return;
-
-       (void)fprintf(fp, "    BH @ %lu (mf: %lu): page %lu; ref %lu",
-           (u_long)R_OFFSET(dbmp, bhp),
-           (u_long)bhp->mf_offset, (u_long)bhp->pgno, (u_long)bhp->ref);
-       sep = "; ";
-       if (F_ISSET(bhp, BH_DIRTY)) {
-               (void)fprintf(fp, "%sdirty", sep);
-               sep = ", ";
-       }
-       if (F_ISSET(bhp, BH_WRITE)) {
-               (void)fprintf(fp, "%schk_write", sep);
-               sep = ", ";
-       }
+       static const FN fn[] = {
+               { BH_CALLPGIN,  "callpgin" },
+               { BH_DIRTY,     "dirty" },
+               { BH_DISCARD,   "discard" },
+               { BH_LOCKED,    "locked" },
+               { BH_TRASH,     "trash" },
+               { BH_WRITE,     "write" },
+               { 0 },
+       };
+       int i;
+
+       for (i = 0; i < FMAP_ENTRIES; ++i)
+               if (fmap[i] == INVALID || fmap[i] == bhp->mf_offset)
+                       break;
+
+       if (fmap[i] == INVALID)
+               (void)fprintf(fp, "  %4lu, %lu, %2lu, %lu",
+                   (u_long)bhp->pgno, (u_long)bhp->mf_offset,
+                   (u_long)bhp->ref, (u_long)R_OFFSET(dbmp, bhp));
+       else
+               (void)fprintf(fp, "  %4lu,   #%d,  %2lu, %lu",
+                   (u_long)bhp->pgno, i + 1,
+                   (u_long)bhp->ref, (u_long)R_OFFSET(dbmp, bhp));
+
+       __db_prflags(bhp->flags, fn, fp);
+
        (void)fprintf(fp, "\n");
 }
index c20e669..6b92fbd 100644 (file)
@@ -1,24 +1,20 @@
 /*-
  * See the file LICENSE for redistribution information.
  *
- * Copyright (c) 1996, 1997
+ * Copyright (c) 1996, 1997, 1998
  *     Sleepycat Software.  All rights reserved.
  */
 #include "config.h"
 
 #ifndef lint
-static const char sccsid[] = "@(#)mp_region.c  10.18 (Sleepycat) 11/29/97";
+static const char sccsid[] = "@(#)mp_region.c  10.30 (Sleepycat) 5/31/98";
 #endif /* not lint */
 
 #ifndef NO_SYSTEM_INCLUDES
 #include <sys/types.h>
-#include <sys/stat.h>
 
 #include <errno.h>
-#include <fcntl.h>
-#include <stdlib.h>
 #include <string.h>
-#include <unistd.h>
 #endif
 
 #include "db_int.h"
@@ -86,7 +82,7 @@ alloc:        if ((ret = __db_shalloc(dbmp->addr, len, MUTEX_ALIGNMENT, &p)) == 0) {
 
                /*
                 * Retry as soon as we've freed up sufficient space.  If we
-                * have to coalesce of memory to satisfy the request, don't
+                * will have to coalesce memory to satisfy the request, don't
                 * try until it's likely (possible?) that we'll succeed.
                 */
                total += fsize = __db_shsizeof(bhp);
@@ -179,18 +175,19 @@ retry:    /* Find a buffer we can flush; pure LRU. */
  *     Attach to, and optionally create, the mpool region.
  *
  * PUBLIC: int __memp_ropen
- * PUBLIC:    __P((DB_MPOOL *, const char *, size_t, int, int));
+ * PUBLIC:    __P((DB_MPOOL *, const char *, size_t, int, int, u_int32_t));
  */
 int
-__memp_ropen(dbmp, path, cachesize, mode, flags)
+__memp_ropen(dbmp, path, cachesize, mode, is_private, flags)
        DB_MPOOL *dbmp;
        const char *path;
        size_t cachesize;
-       int mode, flags;
+       int mode, is_private;
+       u_int32_t flags;
 {
        MPOOL *mp;
        size_t rlen;
-       int fd, newregion, ret, retry_cnt;
+       int defcache, ret;
 
        /*
         * Unlike other DB subsystems, mpool can't simply grow the region
@@ -204,155 +201,107 @@ __memp_ropen(dbmp, path, cachesize, mode, flags)
         *
         * Up the user's cachesize by 25% to account for our overhead.
         */
+       defcache = 0;
        if (cachesize < DB_CACHESIZE_MIN)
-               if (cachesize == 0)
+               if (cachesize == 0) {
+                       defcache = 1;
                        cachesize = DB_CACHESIZE_DEF;
-               else
+               else
                        cachesize = DB_CACHESIZE_MIN;
        rlen = cachesize + cachesize / 4;
 
-       /* Map in the region. */
-       retry_cnt = newregion = 0;
-retry: if (LF_ISSET(DB_CREATE)) {
-               /*
-                * If it's a private mpool, use malloc, it's a lot faster than
-                * instantiating a region.
-                *
-                * XXX
-                * If we're doing locking and don't have spinlocks for this
-                * architecture, we'd have to instantiate the file, we need
-                * the file descriptor for locking.  However, it should not
-                * be possible for DB_THREAD to be set if HAVE_SPINLOCKS aren't
-                * defined.
-                *
-                * XXX
-                * HP-UX won't permit mutexes to live in anything but shared
-                * memory.  So, instantiate the shared mpool region file on
-                * that architecture, regardless.  If this turns out to be a
-                * performance problem, we could use anonymous memory instead.
-                */
-#if !defined(__hppa)
-               if (F_ISSET(dbmp, MP_ISPRIVATE))
-                       if ((dbmp->maddr = __db_malloc(rlen)) == NULL)
-                               ret = ENOMEM;
-                       else {
-                               F_SET(dbmp, MP_MALLOC);
-                               ret = __db_rinit(dbmp->dbenv,
-                                   dbmp->maddr, 0, rlen, 0);
-                       }
-               else
-#endif
-                       ret = __db_rcreate(dbmp->dbenv, DB_APP_NONE, path,
-                           DB_DEFAULT_MPOOL_FILE, mode, rlen,
-                           F_ISSET(dbmp, MP_ISPRIVATE) ? DB_TEMPORARY : 0,
-                           &fd, &dbmp->maddr);
-               if (ret == 0) {
-                       /* Put the MPOOL structure first in the region. */
-                       mp = dbmp->maddr;
-
-                       SH_TAILQ_INIT(&mp->bhq);
-                       SH_TAILQ_INIT(&mp->bhfq);
-                       SH_TAILQ_INIT(&mp->mpfq);
-
-                       /* Initialize the rest of the region as free space. */
-                       dbmp->addr = (u_int8_t *)dbmp->maddr + sizeof(MPOOL);
-                       __db_shalloc_init(dbmp->addr, rlen - sizeof(MPOOL));
-
-                       /*
-                        *
-                        * Pretend that the cache will be broken up into 4K
-                        * pages, and that we want to keep it under, say, 10
-                        * pages on each chain.  This means a 256MB cache will
-                        * allocate ~6500 offset pairs.
-                        */
-                       mp->htab_buckets =
-                           __db_tablesize((cachesize / (4 * 1024)) / 10);
+       /*
+        * Map in the region.
+        *
+        * If it's a private mpool, use malloc, it's a lot faster than
+        * instantiating a region.
+        */
+       dbmp->reginfo.dbenv = dbmp->dbenv;
+       dbmp->reginfo.appname = DB_APP_NONE;
+       if (path == NULL)
+               dbmp->reginfo.path = NULL;
+       else
+               if ((dbmp->reginfo.path = __db_strdup(path)) == NULL)
+                       return (ENOMEM);
+       dbmp->reginfo.file = DB_DEFAULT_MPOOL_FILE;
+       dbmp->reginfo.mode = mode;
+       dbmp->reginfo.size = rlen;
+       dbmp->reginfo.dbflags = flags;
+       dbmp->reginfo.flags = 0;
+       if (defcache)
+               F_SET(&dbmp->reginfo, REGION_SIZEDEF);
 
-                       /* Allocate hash table space and initialize it. */
-                       if ((ret = __db_shalloc(dbmp->addr,
-                           mp->htab_buckets * sizeof(DB_HASHTAB),
-                           0, &dbmp->htab)) != 0)
-                               goto err;
-                       __db_hashinit(dbmp->htab, mp->htab_buckets);
-                       mp->htab = R_OFFSET(dbmp, dbmp->htab);
+       /*
+        * If we're creating a temporary region, don't use any standard
+        * naming.
+        */
+       if (is_private) {
+               dbmp->reginfo.appname = DB_APP_TMP;
+               dbmp->reginfo.file = NULL;
+               F_SET(&dbmp->reginfo, REGION_PRIVATE);
+       }
 
-                       ZERO_LSN(mp->lsn);
-                       mp->lsn_cnt = 0;
+       if ((ret = __db_rattach(&dbmp->reginfo)) != 0) {
+               if (dbmp->reginfo.path != NULL)
+                       FREES(dbmp->reginfo.path);
+               return (ret);
+       }
 
-                       memset(&mp->stat, 0, sizeof(mp->stat));
-                       mp->stat.st_cachesize = cachesize;
+       /*
+        * The MPOOL structure is first in the region, the rest of the region
+        * is free space.
+        */
+       dbmp->mp = dbmp->reginfo.addr;
+       dbmp->addr = (u_int8_t *)dbmp->mp + sizeof(MPOOL);
 
-                       mp->flags = 0;
+       /* Initialize a created region. */
+       if (F_ISSET(&dbmp->reginfo, REGION_CREATED)) {
+               mp = dbmp->mp;
+               SH_TAILQ_INIT(&mp->bhq);
+               SH_TAILQ_INIT(&mp->bhfq);
+               SH_TAILQ_INIT(&mp->mpfq);
 
-                       newregion = 1;
-               } else if (ret != EEXIST)
-                       return (ret);
-       }
+               __db_shalloc_init(dbmp->addr, rlen - sizeof(MPOOL));
 
-       /* If we didn't or couldn't create the region, try and join it. */
-       if (!newregion &&
-           (ret = __db_ropen(dbmp->dbenv, DB_APP_NONE,
-           path, DB_DEFAULT_MPOOL_FILE, 0, &fd, &dbmp->maddr)) != 0) {
                /*
-                * If we failed because the file wasn't available, wait a
-                * second and try again.
+                * Assume we want to keep the hash chains with under 10 pages
+                * on each chain.  We don't know the pagesize in advance, and
+                * it may differ for different files.  Use a pagesize of 1K for
+                * the calculation -- we walk these chains a lot, they should
+                * be short.
                 */
-               if (ret == EAGAIN && ++retry_cnt < 3) {
-                       (void)__db_sleep(1, 0);
-                       goto retry;
-               }
-               return (ret);
-       }
+               mp->htab_buckets =
+                   __db_tablesize((cachesize / (1 * 1024)) / 10);
 
-       /* Set up the common pointers. */
-       dbmp->mp = dbmp->maddr;
-       dbmp->addr = (u_int8_t *)dbmp->maddr + sizeof(MPOOL);
+               /* Allocate hash table space and initialize it. */
+               if ((ret = __db_shalloc(dbmp->addr,
+                   mp->htab_buckets * sizeof(DB_HASHTAB),
+                   0, &dbmp->htab)) != 0)
+                       goto err;
+               __db_hashinit(dbmp->htab, mp->htab_buckets);
+               mp->htab = R_OFFSET(dbmp, dbmp->htab);
 
-       /*
-        * If not already locked, lock the region -- if it's a new region,
-        * then either __db_rcreate() locked it for us or we malloc'd it
-        * instead of creating a region, neither of which requires locking
-        * here.
-        */
-       if (!newregion)
-               LOCKREGION(dbmp);
+               ZERO_LSN(mp->lsn);
+               mp->lsn_cnt = 0;
 
-       /*
-        * Get the hash table address; it's on the shared page, so we have
-        * to lock first.
-        */
-       dbmp->htab = R_ADDR(dbmp, dbmp->mp->htab);
+               memset(&mp->stat, 0, sizeof(mp->stat));
+               mp->stat.st_cachesize = cachesize;
 
-       dbmp->fd = fd;
+               mp->flags = 0;
+       }
 
-       /* If we locked the region, release it now. */
-       if (!F_ISSET(dbmp, MP_MALLOC))
-               UNLOCKREGION(dbmp);
-       return (0);
+       /* Get the local hash table address. */
+       dbmp->htab = R_ADDR(dbmp, dbmp->mp->htab);
 
-err:   if (fd != -1) {
-               dbmp->fd = fd;
-               (void)__memp_rclose(dbmp);
-       }
+       UNLOCKREGION(dbmp);
+       return (0);
 
-       if (newregion)
+err:   UNLOCKREGION(dbmp);
+       (void)__db_rdetach(&dbmp->reginfo);
+       if (F_ISSET(&dbmp->reginfo, REGION_CREATED))
                (void)memp_unlink(path, 1, dbmp->dbenv);
-       return (ret);
-}
 
-/*
- * __memp_rclose --
- *     Close the mpool region.
- *
- * PUBLIC: int __memp_rclose __P((DB_MPOOL *));
- */
-int
-__memp_rclose(dbmp)
-       DB_MPOOL *dbmp;
-{
-       if (F_ISSET(dbmp, MP_MALLOC)) {
-               __db_free(dbmp->maddr);
-               return (0);
-       }
-       return (__db_rclose(dbmp->dbenv, dbmp->fd, dbmp->maddr));
+       if (dbmp->reginfo.path != NULL)
+               FREES(dbmp->reginfo.path);
+       return (ret);
 }
index 6d16cf3..33218ee 100644 (file)
@@ -1,13 +1,13 @@
 /*-
  * See the file LICENSE for redistribution information.
  *
- * Copyright (c) 1996, 1997
+ * Copyright (c) 1996, 1997, 1998
  *     Sleepycat Software.  All rights reserved.
  */
 #include "config.h"
 
 #ifndef lint
-static const char sccsid[] = "@(#)mp_sync.c    10.19 (Sleepycat) 12/3/97";
+static const char sccsid[] = "@(#)mp_sync.c    10.25 (Sleepycat) 4/26/98";
 #endif /* not lint */
 
 #ifndef NO_SYSTEM_INCLUDES
@@ -15,7 +15,6 @@ static const char sccsid[] = "@(#)mp_sync.c   10.19 (Sleepycat) 12/3/97";
 
 #include <errno.h>
 #include <stdlib.h>
-#include <string.h>
 #endif
 
 #include "db_int.h"
@@ -25,6 +24,7 @@ static const char sccsid[] = "@(#)mp_sync.c   10.19 (Sleepycat) 12/3/97";
 #include "common_ext.h"
 
 static int __bhcmp __P((const void *, const void *));
+static int __memp_fsync __P((DB_MPOOLFILE *));
 
 /*
  * memp_sync --
@@ -145,7 +145,8 @@ memp_sync(dbmp, lsnp)
                                bharray[ar_cnt++] = bhp;
                        }
                } else
-                       F_CLR(bhp, BH_WRITE);
+                       if (F_ISSET(bhp, BH_WRITE))
+                               F_CLR(bhp, BH_WRITE);
 
        /* If there no buffers we can write immediately, we're done. */
        if (ar_cnt == 0) {
@@ -235,10 +236,8 @@ int
 memp_fsync(dbmfp)
        DB_MPOOLFILE *dbmfp;
 {
-       BH *bhp, **bharray;
        DB_MPOOL *dbmp;
-       size_t mf_offset;
-       int ar_cnt, cnt, nalloc, next, pincnt, ret, wrote;
+       int is_tmp;
 
        dbmp = dbmfp->dbmp;
 
@@ -250,14 +249,62 @@ memp_fsync(dbmfp)
        if (F_ISSET(dbmfp, MP_READONLY))
                return (0);
 
-       ret = 0;
        LOCKREGION(dbmp);
-       if (F_ISSET(dbmfp->mfp, MP_TEMP))
-               ret = 1;
+       is_tmp = F_ISSET(dbmfp->mfp, MP_TEMP);
        UNLOCKREGION(dbmp);
-       if (ret)
+       if (is_tmp)
                return (0);
 
+       return (__memp_fsync(dbmfp));
+}
+
+/*
+ * __mp_xxx_fd --
+ *     Return a file descriptor for DB 1.85 compatibility locking.
+ *
+ * PUBLIC: int __mp_xxx_fd __P((DB_MPOOLFILE *, int *));
+ */
+int
+__mp_xxx_fd(dbmfp, fdp)
+       DB_MPOOLFILE *dbmfp;
+       int *fdp;
+{
+       int ret;
+
+       /*
+        * This is a truly spectacular layering violation, intended ONLY to
+        * support compatibility for the DB 1.85 DB->fd call.
+        *
+        * Sync the database file to disk, creating the file as necessary.
+        *
+        * We skip the MP_READONLY and MP_TEMP tests done by memp_fsync(3).
+        * The MP_READONLY test isn't interesting because we will either
+        * already have a file descriptor (we opened the database file for
+        * reading) or we aren't readonly (we created the database which
+        * requires write privileges).  The MP_TEMP test isn't interesting
+        * because we want to write to the backing file regardless so that
+        * we get a file descriptor to return.
+        */
+       ret = dbmfp->fd == -1 ? __memp_fsync(dbmfp) : 0;
+
+       return ((*fdp = dbmfp->fd) == -1 ? ENOENT : ret);
+}
+
+/*
+ * __memp_fsync --
+ *     Mpool file internal sync function.
+ */
+static int
+__memp_fsync(dbmfp)
+       DB_MPOOLFILE *dbmfp;
+{
+       BH *bhp, **bharray;
+       DB_MPOOL *dbmp;
+       size_t mf_offset;
+       int ar_cnt, cnt, nalloc, next, pincnt, ret, wrote;
+
+       ret = 0;
+       dbmp = dbmfp->dbmp;
        mf_offset = R_OFFSET(dbmp, dbmfp->mfp);
 
        /*
@@ -359,7 +406,6 @@ err:        UNLOCKREGION(dbmp);
        if (ret == 0)
                return (pincnt == 0 ? __db_fsync(dbmfp->fd) : DB_INCOMPLETE);
        return (ret);
-
 }
 
 /*
@@ -453,8 +499,8 @@ __bhcmp(p1, p2)
 {
        BH *bhp1, *bhp2;
 
-       bhp1 = *(BH **)p1;
-       bhp2 = *(BH **)p2;
+       bhp1 = *(BH * const *)p1;
+       bhp2 = *(BH * const *)p2;
 
        /* Sort by file (shared memory pool offset). */
        if (bhp1->mf_offset < bhp2->mf_offset)
index 9d8be64..21410e6 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * @(#)68020.gcc       10.1 (Sleepycat) 4/12/97
+ * @(#)68020.gcc       10.2 (Sleepycat) 2/15/98
  *
  * For gcc/68K, 0 is clear, 1 is set.
  */
@@ -16,4 +16,3 @@
 
 #define        TSL_UNSET(tsl)  (*(tsl) = 0)
 #define        TSL_INIT(tsl)   TSL_UNSET(tsl)
-
index 6dca323..de0d0e2 100644 (file)
@@ -1,14 +1,14 @@
 /*-
  * See the file LICENSE for redistribution information.
  *
- * Copyright (c) 1996, 1997
+ * Copyright (c) 1996, 1997, 1998
  *     Sleepycat Software.  All rights reserved.
  */
 
 #include "config.h"
 
 #ifndef lint
-static const char sccsid[] = "@(#)mutex.c      10.32 (Sleepycat) 1/16/98";
+static const char sccsid[] = "@(#)mutex.c      10.48 (Sleepycat) 5/23/98";
 #endif /* not lint */
 
 #ifndef NO_SYSTEM_INCLUDES
@@ -16,14 +16,12 @@ static const char sccsid[] = "@(#)mutex.c   10.32 (Sleepycat) 1/16/98";
 
 #include <errno.h>
 #include <fcntl.h>
-#include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 #include <unistd.h>
 #endif
 
 #include "db_int.h"
-#include "common_ext.h"
 
 #ifdef HAVE_SPINLOCKS
 
@@ -43,13 +41,21 @@ static const char sccsid[] = "@(#)mutex.c   10.32 (Sleepycat) 1/16/98";
  * Should we not use MSEM_IF_NOWAIT and let the system block for us?
  * I've no idea if this will block all threads in the process or not.
  */
-#define        TSL_INIT(x)     msem_init(x, MSEM_UNLOCKED)
+#define        TSL_INIT(x)     (msem_init(x, MSEM_UNLOCKED) == NULL)
+#define        TSL_INIT_ERROR  1
 #define        TSL_SET(x)      (!msem_lock(x, MSEM_IF_NOWAIT))
 #define        TSL_UNSET(x)    msem_unlock(x, 0)
 #endif
 
+#ifdef HAVE_FUNC_RELIANT
+#define        TSL_INIT(x)     initspin(x, 1)
+#define        TSL_SET(x)      (cspinlock(x) == 0)
+#define        TSL_UNSET(x)    spinunlock(x)
+#endif
+
 #ifdef HAVE_FUNC_SGI
-#define        TSL_INIT(x)     init_lock(x)
+#define        TSL_INIT(x)     (init_lock(x) != 0)
+#define        TSL_INIT_ERROR  1
 #define        TSL_SET(x)      (!acquire_lock(x))
 #define        TSL_UNSET(x)    release_lock(x)
 #endif
@@ -58,7 +64,8 @@ static const char sccsid[] = "@(#)mutex.c     10.32 (Sleepycat) 1/16/98";
 /*
  * Semaphore calls don't work on Solaris 5.5.
  *
- * #define     TSL_INIT(x)     sema_init(x, 1, USYNC_PROCESS, NULL)
+ * #define     TSL_INIT(x)     (sema_init(x, 1, USYNC_PROCESS, NULL) != 0)
+ * #define     TSL_INIT_ERROR  1
  * #define     TSL_SET(x)      (sema_wait(x) == 0)
  * #define     TSL_UNSET(x)    sema_post(x)
  */
@@ -67,6 +74,10 @@ static const char sccsid[] = "@(#)mutex.c    10.32 (Sleepycat) 1/16/98";
 #define        TSL_UNSET(x)    _lock_clear(x)
 #endif
 
+#ifdef HAVE_ASSEM_PARISC_GCC
+#include "parisc.gcc"
+#endif
+
 #ifdef HAVE_ASSEM_SCO_CC
 #include "sco.cc"
 #endif
@@ -85,17 +96,20 @@ static const char sccsid[] = "@(#)mutex.c   10.32 (Sleepycat) 1/16/98";
 #include "x86.gcc"
 #endif
 
-#if defined(_WIN32)
-/* DBDB this needs to be byte-aligned!! */
+#ifdef WIN16
+/* Win16 spinlocks are simple because we cannot possibly be preempted. */
 #define        TSL_INIT(tsl)
-#define        TSL_SET(tsl)    (!InterlockedExchange((PLONG)tsl, 1))
+#define        TSL_SET(tsl)    (*(tsl) = 1)
 #define        TSL_UNSET(tsl)  (*(tsl) = 0)
 #endif
 
-#ifdef macintosh
-/* Mac spinlocks are simple because we cannot possibly be preempted. */
+#if defined(_WIN32)
+/*
+ * XXX
+ * DBDB this needs to be byte-aligned!!
+ */
 #define        TSL_INIT(tsl)
-#define        TSL_SET(tsl)    (*(tsl) = 1)
+#define        TSL_SET(tsl)    (!InterlockedExchange((PLONG)tsl, 1))
 #define        TSL_UNSET(tsl)  (*(tsl) = 0)
 #endif
 
@@ -105,14 +119,14 @@ static const char sccsid[] = "@(#)mutex.c 10.32 (Sleepycat) 1/16/98";
  * __db_mutex_init --
  *     Initialize a DB mutex structure.
  *
- * PUBLIC: void __db_mutex_init __P((db_mutex_t *, u_int32_t));
+ * PUBLIC: int __db_mutex_init __P((db_mutex_t *, u_int32_t));
  */
-void
+int
 __db_mutex_init(mp, off)
        db_mutex_t *mp;
        u_int32_t off;
 {
-#ifdef DEBUG
+#ifdef DIAGNOSTIC
        if ((ALIGNTYPE)mp & (MUTEX_ALIGNMENT - 1)) {
                (void)fprintf(stderr,
                    "MUTEX ERROR: mutex NOT %d-byte aligned!\n",
@@ -125,11 +139,17 @@ __db_mutex_init(mp, off)
 #ifdef HAVE_SPINLOCKS
        COMPQUIET(off, 0);
 
+#ifdef TSL_INIT_ERROR
+       if (TSL_INIT(&mp->tsl_resource))
+               return (errno);
+#else
        TSL_INIT(&mp->tsl_resource);
+#endif
        mp->spins = __os_spin();
 #else
        mp->off = off;
 #endif
+       return (0);
 }
 
 #define        MS(n)           ((n) * 1000)    /* Milliseconds to micro-seconds. */
@@ -147,17 +167,25 @@ __db_mutex_lock(mp, fd)
        int fd;
 {
        u_long usecs;
-
 #ifdef HAVE_SPINLOCKS
        int nspins;
+#else
+       struct flock k_lock;
+       pid_t mypid;
+       int locked;
+#endif
+
+       if (!DB_GLOBAL(db_mutexlocks))
+               return (0);
 
+#ifdef HAVE_SPINLOCKS
        COMPQUIET(fd, 0);
 
        for (usecs = MS(10);;) {
                /* Try and acquire the uncontested resource lock for N spins. */
                for (nspins = mp->spins; nspins > 0; --nspins)
                        if (TSL_SET(&mp->tsl_resource)) {
-#ifdef DEBUG
+#ifdef DIAGNOSTIC
                                if (mp->pid != 0) {
                                        (void)fprintf(stderr,
                    "MUTEX ERROR: __db_mutex_lock: lock currently locked\n");
@@ -182,9 +210,6 @@ __db_mutex_lock(mp, fd)
        /* NOTREACHED */
 
 #else /* !HAVE_SPINLOCKS */
-       struct flock k_lock;
-       pid_t mypid;
-       int locked;
 
        /* Initialize the lock. */
        k_lock.l_whence = SEEK_SET;
@@ -246,7 +271,10 @@ __db_mutex_unlock(mp, fd)
        db_mutex_t *mp;
        int fd;
 {
-#ifdef DEBUG
+       if (!DB_GLOBAL(db_mutexlocks))
+               return (0);
+
+#ifdef DIAGNOSTIC
        if (mp->pid == 0) {
                (void)fprintf(stderr,
            "MUTEX ERROR: __db_mutex_unlock: lock already unlocked\n");
@@ -257,7 +285,7 @@ __db_mutex_unlock(mp, fd)
 #ifdef HAVE_SPINLOCKS
        COMPQUIET(fd, 0);
 
-#ifdef DEBUG
+#ifdef DIAGNOSTIC
        mp->pid = 0;
 #endif
 
index e15f6f2..2e4540f 100644 (file)
@@ -1,5 +1,5 @@
-/* 
- * @(#)parisc.gcc      8.5 (Sleepycat) 1/18/97
+/*
+ * @(#)parisc.gcc      8.8 (Sleepycat) 6/2/98
  *
  * Copyright (c) 1996-1997, The University of Utah and the Computer Systems
  * Laboratory at the University of Utah (CSL).  All rights reserved.
 
 /*
  * The PA-RISC has a "load and clear" instead of a "test and set" instruction.
- * The 32-bit word used by that instruction must be 16-byte aligned hence we
- * allocate 16 bytes for a tsl_t and use the word that is properly aligned.
- * We could use the "aligned" attribute in GCC but that doesn't work for stack
- * variables.
+ * The 32-bit word used by that instruction must be 16-byte aligned.  We could
+ * use the "aligned" attribute in GCC but that doesn't work for stack variables.
  */
 #define        TSL_SET(tsl) ({                                                 \
-       int *__l = (int *)(((int)(tsl)+15)&~15);                        \
+       register tsl_t *__l = (tsl);                                    \
        int __r;                                                        \
        asm volatile("ldcws 0(%1),%0" : "=r" (__r) : "r" (__l));        \
        __r & 1;                                                        \
 })
 
-#define        TSL_UNSET(tsl) ({                                               \
-       int *__l = (int *)(((int)(tsl)+15)&~15);                        \
-       *__l = -1;                                                      \
-})
+#define        TSL_UNSET(tsl)  (*(tsl) = -1)
+#define        TSL_INIT(tsl)   TSL_UNSET(tsl)
index d10807b..bd0e37f 100644 (file)
@@ -1,5 +1,5 @@
-/* 
- * @(#)parisc.hp       8.5 (Sleepycat) 1/18/97
+/*
+ * @(#)parisc.hp       8.6 (Sleepycat) 6/2/98
  *
  * Copyright (c) 1996-1997, The University of Utah and the Computer Systems
  * Laboratory at the University of Utah (CSL).  All rights reserved.
diff --git a/db2/mutex/sco.cc b/db2/mutex/sco.cc
new file mode 100644 (file)
index 0000000..7c165a2
--- /dev/null
@@ -0,0 +1,24 @@
+/*
+ * @(#)x86.uslc
+ *
+ * UnixWare has threads in libthread, but OpenServer doesn't (yet).
+ *
+ * For cc/x86, 0 is clear, 1 is set.
+ */
+
+#if defined(__USLC__)
+asm int
+_tsl_set(void *tsl)
+{
+%mem tsl
+       movl    tsl, %ecx
+       movl    $1, %eax
+       lock
+       xchgb   (%ecx),%al
+       xorl    $1,%eax
+}
+#endif
+
+#define        TSL_SET(tsl)    _tsl_set(tsl)
+#define        TSL_UNSET(tsl)  (*(tsl) = 0)
+#define        TSL_INIT(tsl)   TSL_UNSET(tsl)
index 872e46d..d9f4970 100644 (file)
@@ -1,14 +1,14 @@
 /*-
  * See the file LICENSE for redistribution information.
  *
- * Copyright (c) 1997
+ * Copyright (c) 1997, 1998
  *     Sleepycat Software.  All rights reserved.
  */
 
 #include "config.h"
 
 #ifndef lint
-static const char sccsid[] = "@(#)os_abs.c     10.7 (Sleepycat) 10/24/97";
+static const char sccsid[] = "@(#)os_abs.c     10.8 (Sleepycat) 4/10/98";
 #endif /* not lint */
 
 #ifndef NO_SYSTEM_INCLUDES
index 27abffb..3578447 100644 (file)
@@ -1,26 +1,46 @@
 /*-
  * See the file LICENSE for redistribution information.
  *
- * Copyright (c) 1997
+ * Copyright (c) 1997, 1998
  *     Sleepycat Software.  All rights reserved.
  */
 
 #include "config.h"
 
 #ifndef lint
-static const char sccsid[] = "@(#)os_alloc.c   10.1 (Sleepycat) 12/1/97";
+static const char sccsid[] = "@(#)os_alloc.c   10.6 (Sleepycat) 5/2/98";
 #endif /* not lint */
 
 #ifndef NO_SYSTEM_INCLUDES
 #include <sys/types.h>
 
-#include <errno.h>
 #include <string.h>
 #endif
 
 #include "db_int.h"
 
 /*
+ * __db_strdup --
+ *     The strdup(3) function for DB.
+ *
+ * PUBLIC: char *__db_strdup __P((const char *));
+ */
+char *
+__db_strdup(str)
+       const char *str;
+{
+       size_t len;
+       char *copy;
+
+       len = strlen(str) + 1;
+       if ((copy = __db_malloc(len)) == NULL)
+               return (NULL);
+
+       memcpy(copy, str, len);
+       return (copy);
+}
+
+/*
  * XXX
  * Correct for systems that return NULL when you allocate 0 bytes of memory.
  * There are several places in DB where we allocate the number of bytes held
@@ -28,6 +48,10 @@ static const char sccsid[] = "@(#)os_alloc.c 10.1 (Sleepycat) 12/1/97";
  * returns a NULL for that reason (which behavior is permitted by ANSI).  We
  * could make these calls macros on non-Alpha architectures (that's where we
  * saw the problem), but it's probably not worth the autoconf complexity.
+ *
+ *     Out of memory.
+ *     We wish to hold the whole sky,
+ *     But we never will.
  */
 /*
  * __db_calloc --
@@ -42,7 +66,7 @@ __db_calloc(num, size)
        void *p;
 
        size *= num;
-       if ((p = __db_jump.db_malloc(size == 0 ? 1 : size)) != NULL)
+       if ((p = __db_jump.j_malloc(size == 0 ? 1 : size)) != NULL)
                memset(p, 0, size);
        return (p);
 }
@@ -57,7 +81,15 @@ void *
 __db_malloc(size)
        size_t size;
 {
-       return (__db_jump.db_malloc(size == 0 ? 1 : size));
+#ifdef DIAGNOSTIC
+       void *p;
+
+       p = __db_jump.j_malloc(size == 0 ? 1 : size);
+       memset(p, 0xff, size == 0 ? 1 : size);
+       return (p);
+#else
+       return (__db_jump.j_malloc(size == 0 ? 1 : size));
+#endif
 }
 
 /*
@@ -71,5 +103,5 @@ __db_realloc(ptr, size)
        void *ptr;
        size_t size;
 {
-       return (__db_jump.db_realloc(ptr, size == 0 ? 1 : size));
+       return (__db_jump.j_realloc(ptr, size == 0 ? 1 : size));
 }
index 7a89ba5..4150c84 100644 (file)
@@ -1,14 +1,14 @@
 /*-
  * See the file LICENSE for redistribution information.
  *
- * Copyright (c) 1997
+ * Copyright (c) 1997, 1998
  *     Sleepycat Software.  All rights reserved.
  */
 
 #include "config.h"
 
 #ifndef lint
-static const char sccsid[] = "@(#)os_config.c  10.12 (Sleepycat) 1/8/98";
+static const char sccsid[] = "@(#)os_config.c  10.26 (Sleepycat) 5/23/98";
 #endif /* not lint */
 
 #ifndef NO_SYSTEM_INCLUDES
@@ -20,22 +20,6 @@ static const char sccsid[] = "@(#)os_config.c        10.12 (Sleepycat) 1/8/98";
 #include "db_int.h"
 
 /*
- * __os_oldwin --
- *     Return if Windows 95 (as opposed to Windows NT).
- *
- * PUBLIC: int __os_oldwin __P((void));
- */
-int
-__os_oldwin()
-{
-#ifdef _WIN32
-       return ((GetVersion() & 0x80000000) != 0);
-#else
-       return (0);
-#endif
-}
-
-/*
  * XXX
  * We provide our own extern declarations so that we don't collide with
  * systems that get them wrong, e.g., SunOS.
@@ -47,13 +31,20 @@ __os_oldwin()
 #define imported
 #endif
 
+/*
+ * XXX
+ * HP/UX MPE doesn't have fsync, but you can build one using FCONTROL.
+ */
+#ifdef __hp3000s900
+#define        fsync   __mpe_fsync
+#endif
+
 imported extern int     close __P((int));
 imported extern void    free __P((void *));
 imported extern int     fsync __P((int));
 imported extern void    *malloc __P((size_t));
 imported extern int     open __P((const char *, int, ...));
 imported extern ssize_t         read __P((int, void *, size_t));
-imported extern char   *strdup __P((const char *));
 imported extern void    *realloc __P((void *, size_t));
 imported extern int     unlink __P((const char *));
 imported extern ssize_t         write __P((int, const void *, size_t));
@@ -63,7 +54,7 @@ imported extern ssize_t        write __P((int, const void *, size_t));
  *     This list of interfaces that applications can replace.  In some
  *     cases, the user is permitted to replace the standard ANSI C or
  *     POSIX 1003.1 call, e.g., malloc or read.  In others, we provide
- *     a local interface to the functionality, e.g., __os_map.
+ *     a local interface to the functionality, e.g., __os_ioinfo.
  */
 struct __db_jumptab __db_jump = {
        close,                          /* DB_FUNC_CLOSE */
@@ -74,20 +65,26 @@ struct __db_jumptab __db_jump = {
        fsync,                          /* DB_FUNC_FSYNC */
        __os_ioinfo,                    /* DB_FUNC_IOINFO */
        malloc,                         /* DB_FUNC_MALLOC */
-       __os_map,                       /* DB_FUNC_MAP */
+       NULL,                           /* DB_FUNC_MAP */
        open,                           /* DB_FUNC_OPEN */
        read,                           /* DB_FUNC_READ */
        realloc,                        /* DB_FUNC_REALLOC */
+       NULL,                           /* DB_FUNC_RUNLINK */
        __os_seek,                      /* DB_FUNC_SEEK */
        __os_sleep,                     /* DB_FUNC_SLEEP */
-       strdup,                         /* DB_FUNC_STRDUP */
        unlink,                         /* DB_FUNC_UNLINK */
-       __os_unmap,                     /* DB_FUNC_UNMAP */
+       NULL,                           /* DB_FUNC_UNMAP */
        write,                          /* DB_FUNC_WRITE */
        NULL                            /* DB_FUNC_YIELD */
 };
 
-int __db_tsl_spins;                    /* DB_TSL_SPINS */
+DB_GLOBALS __db_global_values = {
+       1,                              /* DB_MUTEXLOCKS */
+       0,                              /* DB_REGION_ANON, DB_REGION_NAME */
+       0,                              /* DB_REGION_INIT */
+       0,                              /* DB_TSL_SPINS */
+       0                               /* DB_PAGEYIELD */
+};
 
 /*
  * db_jump_set --
@@ -99,74 +96,68 @@ db_jump_set(func, which)
        int which;
 {
        switch (which) {
-       case DB_FUNC_CALLOC:
-               /*
-                * XXX
-                * Obsolete, calloc is no longer called by DB.
-                */
-                break;
        case DB_FUNC_CLOSE:
-               __db_jump.db_close = (int (*) __P((int)))func;
+               __db_jump.j_close = (int (*) __P((int)))func;
                break;
        case DB_FUNC_DIRFREE:
-               __db_jump.db_dirfree = (void (*) __P((char **, int)))func;
+               __db_jump.j_dirfree = (void (*) __P((char **, int)))func;
                break;
        case DB_FUNC_DIRLIST:
-               __db_jump.db_dirlist =
+               __db_jump.j_dirlist =
                    (int (*) __P((const char *, char ***, int *)))func;
                break;
        case DB_FUNC_EXISTS:
-               __db_jump.db_exists = (int (*) __P((const char *, int *)))func;
+               __db_jump.j_exists = (int (*) __P((const char *, int *)))func;
                break;
        case DB_FUNC_FREE:
-               __db_jump.db_free = (void (*) __P((void *)))func;
+               __db_jump.j_free = (void (*) __P((void *)))func;
                break;
        case DB_FUNC_FSYNC:
-               __db_jump.db_fsync = (int (*) __P((int)))func;
+               __db_jump.j_fsync = (int (*) __P((int)))func;
                break;
        case DB_FUNC_IOINFO:
-               __db_jump.db_ioinfo = (int (*) __P((const char *,
+               __db_jump.j_ioinfo = (int (*) __P((const char *,
                    int, u_int32_t *, u_int32_t *, u_int32_t *)))func;
                break;
        case DB_FUNC_MALLOC:
-               __db_jump.db_malloc = (void *(*) __P((size_t)))func;
+               __db_jump.j_malloc = (void *(*) __P((size_t)))func;
                break;
        case DB_FUNC_MAP:
-               __db_jump.db_map =
-                   (int (*) __P((int, size_t, int, int, void **)))func;
+               __db_jump.j_map = (int (*)
+                   __P((char *, int, size_t, int, int, int, void **)))func;
                break;
        case DB_FUNC_OPEN:
-               __db_jump.db_open = (int (*) __P((const char *, int, ...)))func;
+               __db_jump.j_open = (int (*) __P((const char *, int, ...)))func;
                break;
        case DB_FUNC_READ:
-               __db_jump.db_read =
+               __db_jump.j_read =
                    (ssize_t (*) __P((int, void *, size_t)))func;
                break;
        case DB_FUNC_REALLOC:
-               __db_jump.db_realloc = (void *(*) __P((void *, size_t)))func;
+               __db_jump.j_realloc = (void *(*) __P((void *, size_t)))func;
+               break;
+       case DB_FUNC_RUNLINK:
+               __db_jump.j_runlink = (int (*) __P((char *)))func;
                break;
        case DB_FUNC_SEEK:
-               __db_jump.db_seek =
-                   (int (*) __P((int, size_t, db_pgno_t, u_long, int)))func;
+               __db_jump.j_seek = (int (*)
+                   __P((int, size_t, db_pgno_t, u_int32_t, int, int)))func;
                break;
        case DB_FUNC_SLEEP:
-               __db_jump.db_sleep = (int (*) __P((u_long, u_long)))func;
-               break;
-       case DB_FUNC_STRDUP:
-               __db_jump.db_strdup = (char *(*) __P((const char *)))func;
+               __db_jump.j_sleep = (int (*) __P((u_long, u_long)))func;
                break;
        case DB_FUNC_UNLINK:
-               __db_jump.db_unlink = (int (*) __P((const char *)))func;
+               __db_jump.j_unlink = (int (*) __P((const char *)))func;
                break;
        case DB_FUNC_UNMAP:
-               __db_jump.db_unmap = (int (*) __P((void *, size_t)))func;
+               __db_jump.j_unmap = (int (*) __P((void *, size_t)))func;
                break;
        case DB_FUNC_WRITE:
-               __db_jump.db_write =
+               __db_jump.j_write =
                    (ssize_t (*) __P((int, const void *, size_t)))func;
                break;
        case DB_FUNC_YIELD:
-               __db_jump.db_yield = (int (*) __P((void)))func;
+               __db_jump.j_yield = (int (*) __P((void)))func;
                break;
        default:
                return (EINVAL);
@@ -182,11 +173,32 @@ int
 db_value_set(value, which)
        int value, which;
 {
+       int ret;
+
        switch (which) {
+       case DB_MUTEXLOCKS:
+               DB_GLOBAL(db_mutexlocks) = value;
+               break;
+       case DB_PAGEYIELD:
+               DB_GLOBAL(db_pageyield) = value;
+               break;
+       case DB_REGION_ANON:
+               if (value != 0 && (ret = __db_mapanon_ok(0)) != 0)
+                       return (ret);
+               DB_GLOBAL(db_region_anon) = value;
+               break;
+       case DB_REGION_INIT:
+               DB_GLOBAL(db_region_init) = value;
+               break;
+       case DB_REGION_NAME:
+               if (value != 0 && (ret = __db_mapanon_ok(1)) != 0)
+                       return (ret);
+               DB_GLOBAL(db_region_anon) = value;
+               break;
        case DB_TSL_SPINS:
                if (value <= 0)
                        return (EINVAL);
-               __db_tsl_spins = value;
+               DB_GLOBAL(db_tsl_spins) = value;
                break;
        default:
                return (EINVAL);
index 10fb8b6..14a10ad 100644 (file)
@@ -1,14 +1,14 @@
 /*-
  * See the file LICENSE for redistribution information.
  *
- * Copyright (c) 1997
+ * Copyright (c) 1997, 1998
  *     Sleepycat Software.  All rights reserved.
  */
 
 #include "config.h"
 
 #ifndef lint
-static const char sccsid[] = "@(#)os_dir.c     10.13 (Sleepycat) 10/28/97";
+static const char sccsid[] = "@(#)os_dir.c     10.15 (Sleepycat) 4/26/98";
 #endif /* not lint */
 
 #ifndef NO_SYSTEM_INCLUDES
@@ -32,13 +32,9 @@ static const char sccsid[] = "@(#)os_dir.c   10.13 (Sleepycat) 10/28/97";
 #endif
 
 #include <errno.h>
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
 #endif
 
 #include "db_int.h"
-#include "common_ext.h"
 
 /*
  * __os_dirlist --
index 6820b88..cf48c01 100644 (file)
@@ -1,14 +1,14 @@
 /*-
  * See the file LICENSE for redistribution information.
  *
- * Copyright (c) 1996, 1997
+ * Copyright (c) 1996, 1997, 1998
  *     Sleepycat Software.  All rights reserved.
  */
 
 #include "config.h"
 
 #ifndef lint
-static const char sccsid[] = "@(#)os_fid.c     10.9 (Sleepycat) 10/24/97";
+static const char sccsid[] = "@(#)os_fid.c     10.11 (Sleepycat) 4/26/98";
 #endif /* not lint */
 
 #ifndef NO_SYSTEM_INCLUDES
@@ -16,7 +16,6 @@ static const char sccsid[] = "@(#)os_fid.c    10.9 (Sleepycat) 10/24/97";
 #include <sys/stat.h>
 
 #include <errno.h>
-#include <stdlib.h>
 #include <string.h>
 #include <time.h>
 #endif
index 7b001ce..e1f271a 100644 (file)
@@ -1,14 +1,14 @@
 /*-
  * See the file LICENSE for redistribution information.
  *
- * Copyright (c) 1997
+ * Copyright (c) 1997, 1998
  *     Sleepycat Software.  All rights reserved.
  */
 
 #include "config.h"
 
 #ifndef lint
-static const char sccsid[] = "@(#)os_fsync.c   10.3 (Sleepycat) 10/25/97";
+static const char sccsid[] = "@(#)os_fsync.c   10.5 (Sleepycat) 4/19/98";
 #endif /* not lint */
 
 #ifndef NO_SYSTEM_INCLUDES
@@ -32,3 +32,18 @@ __db_fsync(fd)
 {
        return (__os_fsync(fd) ? errno : 0);
 }
+
+#ifdef __hp3000s900
+#include <fcntl.h>
+
+int
+__mpe_fsync(fd)
+       int fd;
+{
+       extern FCONTROL(short, short, void *);
+
+       FCONTROL(_MPE_FILENO(fd), 2, NULL);     /* Flush the buffers */
+       FCONTROL(_MPE_FILENO(fd), 6, NULL);     /* Write the EOF */
+       return (0);
+}
+#endif
index b155318..5f0fd79 100644 (file)
 /*-
  * See the file LICENSE for redistribution information.
  *
- * Copyright (c) 1996, 1997
+ * Copyright (c) 1996, 1997, 1998
  *     Sleepycat Software.  All rights reserved.
  */
 
 #include "config.h"
 
 #ifndef lint
-static const char sccsid[] = "@(#)os_map.c     10.7 (Sleepycat) 10/25/97";
+static const char sccsid[] = "@(#)os_map.c     10.19 (Sleepycat) 5/3/98";
 #endif /* not lint */
 
 #ifndef NO_SYSTEM_INCLUDES
 #include <sys/types.h>
+#ifdef HAVE_MMAP
 #include <sys/mman.h>
+#endif
+
+#ifdef HAVE_SHMGET
+#include <sys/ipc.h>
+#include <sys/shm.h>
+#endif
 
 #include <errno.h>
+#include <string.h>
 #endif
 
 #include "db_int.h"
+#include "common_ext.h"
+
+#ifdef HAVE_MMAP
+static int __os_map __P((char *, int, size_t, int, int, int, void **));
+#endif
+#ifdef HAVE_SHMGET
+static int __os_shmget __P((char *, REGINFO *));
+#endif
 
 /*
- * __os_map --
- *     Map in some shared memory backed by a file descriptor.
+ * __db_mapanon_ok --
+ *     Return if this OS can support anonymous memory regions.
+ *
+ * PUBLIC: int __db_mapanon_ok __P((int));
+ */
+int
+__db_mapanon_ok(need_names)
+       int need_names;
+{
+       int ret;
+
+       ret = EINVAL;
+
+       /*
+        * If we don't have spinlocks, we have to have a file descriptor
+        * for fcntl(2) locking, which implies using mmap(2) to map in a
+        * regular file.  Theoretically, we could probably find ways to
+        * get a file descriptor to lock other types of shared regions,
+        * but I don't see any reason to do so.
+        *
+        * If need_names is set, the application wants to share anonymous
+        * memory among multiple processes, so we have to have a way to
+        * name it.  This requires shmget(2), on UNIX systems.
+        */
+#ifdef HAVE_SPINLOCKS
+#ifdef HAVE_SHMGET
+       ret = 0;
+#endif
+#ifdef HAVE_MMAP
+#ifdef MAP_ANON
+       if (!need_names)
+               ret = 0;
+#endif
+#ifdef MAP_ANONYMOUS
+       if (!need_names)
+               ret = 0;
+#endif
+#else
+       COMPQUIET(need_names, 0);
+#endif /* HAVE_MMAP */
+#endif /* HAVE_SPINLOCKS */
+
+       return (ret);
+}
+
+/*
+ * __db_mapinit --
+ *     Return if shared regions need to be initialized.
+ *
+ * PUBLIC: int __db_mapinit __P((void));
+ */
+int
+__db_mapinit()
+{
+       /*
+        * Historically, some systems required that all of the bytes of the
+        * region be written before it could be mmapped and accessed randomly.
+        * We have the option of setting REGION_INIT_NEEDED at configuration
+        * time if we're running on one of those systems.
+        */
+#ifdef REGION_INIT_NEEDED
+       return (1);
+#else
+       return (0);
+#endif
+}
+
+/*
+ * __db_mapregion --
+ *     Attach to a shared memory region.
+ *
+ * PUBLIC: int __db_mapregion __P((char *, REGINFO *));
+ */
+int
+__db_mapregion(path, infop)
+       char *path;
+       REGINFO *infop;
+{
+       int called, ret;
+
+       called = 0;
+       ret = EINVAL;
+
+       /* If the user replaces the map call, call through their interface. */
+       if (__db_jump.j_map != NULL) {
+               F_SET(infop, REGION_HOLDINGSYS);
+               return (__db_jump.j_map(path, infop->fd, infop->size,
+                   1, F_ISSET(infop, REGION_ANONYMOUS), 0, &infop->addr));
+       }
+
+       if (F_ISSET(infop, REGION_ANONYMOUS)) {
+               /*
+                * !!!
+                * If we're creating anonymous regions:
+                *
+                * If it's private, we use mmap(2).  The problem with using
+                * shmget(2) is that we may be creating a region of which the
+                * application isn't aware, and if the application crashes
+                * we'll have no way to remove the system resources for the
+                * region.
+                *
+                * If it's not private, we use the shmget(2) interface if it's
+                * available, because it allows us to name anonymous memory.
+                * If shmget(2) isn't available, use the mmap(2) calls.
+                *
+                * In the case of anonymous memory, using mmap(2) means the
+                * memory isn't named and only the single process and its
+                * threads can access the region.
+                */
+#ifdef HAVE_MMAP
+#ifdef MAP_ANON
+#define        HAVE_MMAP_ANONYMOUS     1
+#else
+#ifdef MAP_ANONYMOUS
+#define        HAVE_MMAP_ANONYMOUS     1
+#endif
+#endif
+#endif
+#ifdef HAVE_MMAP_ANONYMOUS
+               if (!called && F_ISSET(infop, REGION_PRIVATE)) {
+                       called = 1;
+                       ret = __os_map(path,
+                           infop->fd, infop->size, 1, 1, 0, &infop->addr);
+               }
+#endif
+#ifdef HAVE_SHMGET
+               if (!called) {
+                       called = 1;
+                       ret = __os_shmget(path, infop);
+               }
+#endif
+#ifdef HAVE_MMAP
+               /*
+                * If we're trying to join an unnamed anonymous region, fail --
+                * that's not possible.
+                */
+               if (!called) {
+                       called = 1;
+
+                       if (!F_ISSET(infop, REGION_CREATED)) {
+                               __db_err(infop->dbenv,
+                           "cannot join region in unnamed anonymous memory");
+                               return (EINVAL);
+                       }
+
+                       ret = __os_map(path,
+                           infop->fd, infop->size, 1, 1, 0, &infop->addr);
+               }
+#endif
+       } else {
+               /*
+                * !!!
+                * If we're creating normal regions, we use the mmap(2)
+                * interface if it's available because it's POSIX 1003.1
+                * standard and we trust it more than we do shmget(2).
+                */
+#ifdef HAVE_MMAP
+               if (!called) {
+                       called = 1;
+
+                       /* Mmap(2) regions that aren't anonymous can grow. */
+                       F_SET(infop, REGION_CANGROW);
+
+                       ret = __os_map(path,
+                           infop->fd, infop->size, 1, 0, 0, &infop->addr);
+               }
+#endif
+#ifdef HAVE_SHMGET
+               if (!called) {
+                       called = 1;
+                       ret = __os_shmget(path, infop);
+               }
+#endif
+       }
+       return (ret);
+}
+
+/*
+ * __db_unmapregion --
+ *     Detach from the shared memory region.
+ *
+ * PUBLIC: int __db_unmapregion __P((REGINFO *));
+ */
+int
+__db_unmapregion(infop)
+       REGINFO *infop;
+{
+       int called, ret;
+
+       called = 0;
+       ret = EINVAL;
+
+       if (__db_jump.j_unmap != NULL)
+               return (__db_jump.j_unmap(infop->addr, infop->size));
+
+#ifdef HAVE_SHMGET
+       if (infop->segid != INVALID_SEGID) {
+               called = 1;
+               ret = shmdt(infop->addr) ? errno : 0;
+       }
+#endif
+#ifdef HAVE_MMAP
+       if (!called) {
+               called = 1;
+               ret = munmap(infop->addr, infop->size) ? errno : 0;
+       }
+#endif
+       return (ret);
+}
+
+/*
+ * __db_unlinkregion --
+ *     Remove the shared memory region.
+ *
+ * PUBLIC: int __db_unlinkregion __P((char *, REGINFO *));
+ */
+int
+__db_unlinkregion(name, infop)
+       char *name;
+       REGINFO *infop;
+{
+       int called, ret;
+
+       called = 0;
+       ret = EINVAL;
+
+       if (__db_jump.j_runlink != NULL)
+               return (__db_jump.j_runlink(name));
+
+#ifdef HAVE_SHMGET
+       if (infop->segid != INVALID_SEGID) {
+               called = 1;
+               ret = shmctl(infop->segid, IPC_RMID, NULL) ? errno : 0;
+       }
+#else
+       COMPQUIET(infop, NULL);
+#endif
+#ifdef HAVE_MMAP
+       if (!called) {
+               called = 1;
+               ret = 0;
+       }
+#endif
+       return (ret);
+}
+
+/*
+ * __db_mapfile --
+ *     Map in a shared memory file.
+ *
+ * PUBLIC: int __db_mapfile __P((char *, int, size_t, int, void **));
+ */
+int
+__db_mapfile(path, fd, len, is_rdonly, addr)
+       char *path;
+       int fd, is_rdonly;
+       size_t len;
+       void **addr;
+{
+       if (__db_jump.j_map != NULL)
+               return (__db_jump.j_map(path, fd, len, 0, 0, is_rdonly, addr));
+
+#ifdef HAVE_MMAP
+       return (__os_map(path, fd, len, 0, 0, is_rdonly, addr));
+#else
+       return (EINVAL);
+#endif
+}
+
+/*
+ * __db_unmapfile --
+ *     Unmap the shared memory file.
  *
- * PUBLIC: int __os_map __P((int, size_t, int, int, void **));
+ * PUBLIC: int __db_unmapfile __P((void *, size_t));
  */
 int
-__os_map(fd, len, is_private, is_rdonly, addr)
-       int fd, is_private, is_rdonly;
+__db_unmapfile(addr, len)
+       void *addr;
+       size_t len;
+{
+       if (__db_jump.j_unmap != NULL)
+               return (__db_jump.j_unmap(addr, len));
+
+#ifdef HAVE_MMAP
+       return (munmap(addr, len) ? errno : 0);
+#else
+       return (EINVAL);
+#endif
+}
+
+#ifdef HAVE_MMAP
+/*
+ * __os_map --
+ *     Call the mmap(2) function.
+ */
+static int
+__os_map(path, fd, len, is_region, is_anonymous, is_rdonly, addr)
+       char *path;
+       int fd, is_region, is_anonymous, is_rdonly;
        size_t len;
        void **addr;
 {
        void *p;
        int flags, prot;
 
-       flags = is_private ? MAP_PRIVATE : MAP_SHARED;
+       COMPQUIET(path, NULL);
+
+       /*
+        * If it's read-only, it's private, and if it's not, it's shared.
+        * Don't bother with an additional parameter.
+        */
+       flags = is_rdonly ? MAP_PRIVATE : MAP_SHARED;
+
+       if (is_region && is_anonymous) {
+               /*
+                * BSD derived systems use MAP_ANON; Digital Unix and HP/UX
+                * use MAP_ANONYMOUS.
+                */
+#ifdef MAP_ANON
+               flags |= MAP_ANON;
+#endif
+#ifdef MAP_ANONYMOUS
+               flags |= MAP_ANONYMOUS;
+#endif
+               fd = -1;
+       }
+#ifdef MAP_FILE
+       if (!is_region || !is_anonymous) {
+               /*
+                * Historically, MAP_FILE was required for mapping regular
+                * files, even though it was the default.  Some systems have
+                * it, some don't, some that have it set it to 0.
+                */
+               flags |= MAP_FILE;
+       }
+#endif
+
+       /*
+        * I know of no systems that implement the flag to tell the system
+        * that the region contains semaphores, but it's not an unreasonable
+        * thing to do, and has been part of the design since forever.  I
+        * don't think anyone will object, but don't set it for read-only
+        * files, it doesn't make sense.
+        */
 #ifdef MAP_HASSEMAPHORE
-       flags |= MAP_HASSEMAPHORE;
+       if (!is_rdonly)
+               flags |= MAP_HASSEMAPHORE;
 #endif
+
        prot = PROT_READ | (is_rdonly ? 0 : PROT_WRITE);
 
-#ifndef MAP_FAILED                     /* XXX: Mmap(2) failure return. */
+       /* MAP_FAILED was not defined in early mmap implementations. */
+#ifndef MAP_FAILED
 #define        MAP_FAILED      -1
 #endif
        if ((p =
@@ -51,21 +399,67 @@ __os_map(fd, len, is_private, is_rdonly, addr)
        *addr = p;
        return (0);
 }
+#endif
 
+#ifdef HAVE_SHMGET
 /*
- * __os_unmap --
- *     Release the specified shared memory.
- *
- * PUBLIC: int __os_unmap __P((void *, size_t));
+ * __os_shmget --
+ *     Call the shmget(2) family of functions.
  */
-int
-__os_unmap(addr, len)
-       void *addr;
-       size_t len;
+static int
+__os_shmget(path, infop)
+       REGINFO *infop;
+       char *path;
 {
-       /*
-        * !!!
-        * The argument len is always the same length as was mapped.
-        */
-       return (munmap(addr, len) ? errno : 0);
+       key_t key;
+       int shmflg;
+
+       if (F_ISSET(infop, REGION_CREATED)) {
+               /*
+                * The return key from ftok(3) is not guaranteed to be unique.
+                * The nice thing about the shmget(2) interface is that it
+                * allows you to name anonymous pieces of memory.  The evil
+                * thing about it is that the name space is separate from the
+                * filesystem.
+                */
+#ifdef __hp3000s900
+               {char mpe_path[MAXPATHLEN];
+               /*
+                * MPE ftok() is broken as of 5.5pp4.  If the file path does
+                * not start with '/' or '.', then ftok() tries to interpret
+                * the file path in MPE syntax instead of POSIX HFS syntax.
+                * The workaround is to prepend "./" to these paths.  See HP
+                * SR 5003416081 for details.
+                */
+               if (*path != '/' && *path != '.') {
+                       if (strlen(path) + strlen("./") + 1 > sizeof(mpe_path))
+                               return (ENAMETOOLONG);
+                       mpe_path[0] = '.';
+                       mpe_path[1] = '/';
+                       (void)strcpy(mpe_path + 2, path);
+                       path = mpe_path;
+               }
+               }
+#endif
+               if ((key = ftok(path, 1)) == (key_t)-1)
+                       return (errno);
+
+               shmflg = IPC_CREAT | 0600;
+               if ((infop->segid = shmget(key, infop->size, shmflg)) == -1)
+                       return (errno);
+       }
+
+       if ((infop->addr = shmat(infop->segid, NULL, 0)) == (void *)-1) {
+               /*
+                * If we're trying to join the region and failing, assume
+                * that there was a reboot and the region no longer exists.
+                */
+               if (!F_ISSET(infop, REGION_CREATED))
+                       errno = EAGAIN;
+               return (errno);
+       }
+
+       F_SET(infop, REGION_HOLDINGSYS);
+       return (0);
 }
+#endif
index 3656eef..388c1c6 100644 (file)
@@ -1,18 +1,19 @@
 /*-
  * See the file LICENSE for redistribution information.
  *
- * Copyright (c) 1997
+ * Copyright (c) 1997, 1998
  *     Sleepycat Software.  All rights reserved.
  */
 
 #include "config.h"
 
 #ifndef lint
-static const char sccsid[] = "@(#)os_oflags.c  10.2 (Sleepycat) 10/24/97";
+static const char sccsid[] = "@(#)os_oflags.c  10.6 (Sleepycat) 4/19/98";
 #endif /* not lint */
 
 #ifndef NO_SYSTEM_INCLUDES
 #include <sys/types.h>
+#include <sys/stat.h>
 
 #include <fcntl.h>
 #endif
@@ -23,13 +24,13 @@ static const char sccsid[] = "@(#)os_oflags.c       10.2 (Sleepycat) 10/24/97";
  * __db_oflags --
  *     Convert open(2) flags to DB flags.
  *
- * PUBLIC: int __db_oflags __P((int));
+ * PUBLIC: u_int32_t __db_oflags __P((int));
  */
-int
+u_int32_t
 __db_oflags(oflags)
        int oflags;
 {
-       int dbflags;
+       u_int32_t dbflags;
 
        /*
         * XXX
@@ -46,3 +47,48 @@ __db_oflags(oflags)
                dbflags |= DB_TRUNCATE;
        return (dbflags);
 }
+
+/*
+ * __db_omode --
+ *     Convert a permission string to the correct open(2) flags.
+ *
+ * PUBLIC: int __db_omode __P((const char *));
+ */
+int
+__db_omode(perm)
+       const char *perm;
+{
+       int mode;
+
+#ifndef        S_IRUSR
+#if defined(_WIN32) || defined(WIN16)
+#define        S_IRUSR S_IREAD         /* R for owner */
+#define        S_IWUSR S_IWRITE        /* W for owner */
+#define        S_IRGRP 0               /* R for group */
+#define        S_IWGRP 0               /* W for group */
+#define        S_IROTH 0               /* R for other */
+#define        S_IWOTH 0               /* W for other */
+#else
+#define        S_IRUSR 0000400         /* R for owner */
+#define        S_IWUSR 0000200         /* W for owner */
+#define        S_IRGRP 0000040         /* R for group */
+#define        S_IWGRP 0000020         /* W for group */
+#define        S_IROTH 0000004         /* R for other */
+#define        S_IWOTH 0000002         /* W for other */
+#endif /* _WIN32 || WIN16 */
+#endif
+       mode = 0;
+       if (perm[0] == 'r')
+               mode |= S_IRUSR;
+       if (perm[1] == 'w')
+               mode |= S_IWUSR;
+       if (perm[2] == 'r')
+               mode |= S_IRGRP;
+       if (perm[3] == 'w')
+               mode |= S_IWGRP;
+       if (perm[4] == 'r')
+               mode |= S_IROTH;
+       if (perm[5] == 'w')
+               mode |= S_IWOTH;
+       return (mode);
+}
index a628765..e960377 100644 (file)
@@ -1,14 +1,14 @@
 /*-
  * See the file LICENSE for redistribution information.
  *
- * Copyright (c) 1997
+ * Copyright (c) 1997, 1998
  *     Sleepycat Software.  All rights reserved.
  */
 
 #include "config.h"
 
 #ifndef lint
-static const char sccsid[] = "@(#)os_open.c    10.20 (Sleepycat) 11/27/97";
+static const char sccsid[] = "@(#)os_open.c    10.26 (Sleepycat) 5/4/98";
 #endif /* not lint */
 
 #ifndef NO_SYSTEM_INCLUDES
@@ -25,12 +25,13 @@ static const char sccsid[] = "@(#)os_open.c 10.20 (Sleepycat) 11/27/97";
  * __db_open --
  *     Open a file descriptor.
  *
- * PUBLIC: int __db_open __P((const char *, int, int, int, int *));
+ * PUBLIC: int __db_open __P((const char *, u_int32_t, u_int32_t, int, int *));
  */
 int
 __db_open(name, arg_flags, ok_flags, mode, fdp)
        const char *name;
-       int arg_flags, ok_flags, mode, *fdp;
+       u_int32_t arg_flags, ok_flags;
+       int mode, *fdp;
 {
        int fd, flags;
 
@@ -54,7 +55,7 @@ __db_open(name, arg_flags, ok_flags, mode, fdp)
        else
                flags |= O_RDWR;
 
-#ifdef _WIN32
+#if defined(_WIN32) || defined(WIN16)
 #ifdef _MSC_VER
        if (arg_flags & DB_SEQUENTIAL)
                flags |= _O_SEQUENTIAL;
@@ -80,7 +81,7 @@ __db_open(name, arg_flags, ok_flags, mode, fdp)
                (void)__os_unlink(name);
 #endif
 
-#if !defined(_WIN32) && !defined(macintosh)
+#if !defined(_WIN32) && !defined(WIN16)
        /*
         * Deny access to any child process; done for Win32 by O_NOINHERIT,
         * MacOS has neither child processes nor fd inheritance.
index 44fd4ec..23867b3 100644 (file)
@@ -1,14 +1,14 @@
 /*-
  * See the file LICENSE for redistribution information.
  *
- * Copyright (c) 1997
+ * Copyright (c) 1997, 1998
  *     Sleepycat Software.  All rights reserved.
  */
 
 #include "config.h"
 
 #ifndef lint
-static const char sccsid[] = "@(#)os_rpath.c   10.2 (Sleepycat) 10/24/97";
+static const char sccsid[] = "@(#)os_rpath.c   10.3 (Sleepycat) 4/10/98";
 #endif /* not lint */
 
 #ifndef NO_SYSTEM_INCLUDES
index 48f7fdc..7591041 100644 (file)
@@ -1,14 +1,14 @@
 /*-
  * See the file LICENSE for redistribution information.
  *
- * Copyright (c) 1997
+ * Copyright (c) 1997, 1998
  *     Sleepycat Software.  All rights reserved.
  */
 
 #include "config.h"
 
 #ifndef lint
-static const char sccsid[] = "@(#)os_rw.c      10.6 (Sleepycat) 10/25/97";
+static const char sccsid[] = "@(#)os_rw.c      10.7 (Sleepycat) 4/10/98";
 #endif /* not lint */
 
 #ifndef NO_SYSTEM_INCLUDES
index e27044b..159425c 100644 (file)
@@ -1,14 +1,14 @@
 /*-
  * See the file LICENSE for redistribution information.
  *
- * Copyright (c) 1997
+ * Copyright (c) 1997, 1998
  *     Sleepycat Software.  All rights reserved.
  */
 
 #include "config.h"
 
 #ifndef lint
-static const char sccsid[] = "@(#)os_seek.c    10.6 (Sleepycat) 10/25/97";
+static const char sccsid[] = "@(#)os_seek.c    10.9 (Sleepycat) 4/19/98";
 #endif /* not lint */
 
 #ifndef NO_SYSTEM_INCLUDES
@@ -24,19 +24,21 @@ static const char sccsid[] = "@(#)os_seek.c 10.6 (Sleepycat) 10/25/97";
  * __os_seek --
  *     Seek to a page/byte offset in the file.
  *
- * PUBLIC: int __os_seek __P((int, size_t, db_pgno_t, u_long, int));
+ * PUBLIC: int __os_seek __P((int, size_t, db_pgno_t, u_int32_t, int, int));
  */
 int
-__os_seek(fd, pgsize, pageno, relative, whence)
+__os_seek(fd, pgsize, pageno, relative, isrewind, whence)
        int fd;
        size_t pgsize;
        db_pgno_t pageno;
-       u_long relative;
-       int whence;
+       u_int32_t relative;
+       int isrewind, whence;
 {
        off_t offset;
 
-       offset = pgsize * pageno + relative;
+       offset = (off_t)pgsize * pageno + relative;
+       if (isrewind)
+               offset = -offset;
 
        return (lseek(fd, offset, whence) == -1 ? errno : 0);
 }
index 2d2cb71..6a5b91f 100644 (file)
@@ -1,14 +1,14 @@
 /*-
  * See the file LICENSE for redistribution information.
  *
- * Copyright (c) 1997
+ * Copyright (c) 1997, 1998
  *     Sleepycat Software.  All rights reserved.
  */
 
 #include "config.h"
 
 #ifndef lint
-static const char sccsid[] = "@(#)os_sleep.c   10.8 (Sleepycat) 10/25/97";
+static const char sccsid[] = "@(#)os_sleep.c   10.10 (Sleepycat) 4/27/98";
 #endif /* not lint */
 
 #ifndef NO_SYSTEM_INCLUDES
@@ -42,7 +42,8 @@ __os_sleep(secs, usecs)
        struct timeval t;
 
        /* Don't require that the values be normalized. */
-       for (; usecs >= 1000000; ++secs, usecs -= 1000000);
+       for (; usecs >= 1000000; ++secs, usecs -= 1000000)
+               ;
 
        /*
         * It's important that we yield the processor here so that other
index fb693c2..2fd21d0 100644 (file)
@@ -1,14 +1,14 @@
 /*-
  * See the file LICENSE for redistribution information.
  *
- * Copyright (c) 1997
+ * Copyright (c) 1997, 1998
  *     Sleepycat Software.  All rights reserved.
  */
 
 #include "config.h"
 
 #ifndef lint
-static const char sccsid[] = "@(#)os_spin.c    10.3 (Sleepycat) 11/25/97";
+static const char sccsid[] = "@(#)os_spin.c    10.7 (Sleepycat) 5/20/98";
 #endif /* not lint */
 
 #ifndef NO_SYSTEM_INCLUDES
@@ -29,28 +29,33 @@ static const char sccsid[] = "@(#)os_spin.c 10.3 (Sleepycat) 11/25/97";
 int
 __os_spin()
 {
-       extern int __db_tsl_spins;
+       static long sys_val;
 
        /* If the application specified the spins, use its value. */
-       if (__db_tsl_spins != 0)
-               return (__db_tsl_spins);
+       if (DB_GLOBAL(db_tsl_spins) != 0)
+               return (DB_GLOBAL(db_tsl_spins));
+
+       /* If we've already figured this out, return the value. */
+       if (sys_val != 0)
+               return (sys_val);
 
        /*
         * XXX
-        * Sysconf: Solaris uses _SC_NPROCESSORS_ONLN to return the number
-        * of online processors.  I don't know if this call is portable or
-        * not.
+        * Solaris and Linux use _SC_NPROCESSORS_ONLN to return the number of
+        * online processors.  We don't want to repeatedly call sysconf because
+        * it's quite expensive (requiring multiple filesystem accesses) under
+        * Debian Linux.
+        *
+        * Spin 50 times per processor -- we have anecdotal evidence that this
+        * is a reasonable value.
         */
 #if defined(HAVE_SYSCONF) && defined(_SC_NPROCESSORS_ONLN)
-       {
-               long sys_val;
-
-               sys_val = sysconf(_SC_NPROCESSORS_ONLN);
-               if (sys_val > 0)
-                       return (sys_val * 50);
-       }
+       if ((sys_val = sysconf(_SC_NPROCESSORS_ONLN)) > 1)
+               sys_val *= 50;
+       else
+               sys_val = 1;
+#else
+       sys_val = 1;
 #endif
-
-       /* Default to a single processor. */
-       return (1);
+       return (sys_val);
 }
index 73600b6..e7d3f24 100644 (file)
@@ -1,14 +1,14 @@
 /*-
  * See the file LICENSE for redistribution information.
  *
- * Copyright (c) 1997
+ * Copyright (c) 1997, 1998
  *     Sleepycat Software.  All rights reserved.
  */
 
 #include "config.h"
 
 #ifndef lint
-static const char sccsid[] = "@(#)os_stat.c    10.11 (Sleepycat) 1/8/98";
+static const char sccsid[] = "@(#)os_stat.c    10.15 (Sleepycat) 4/27/98";
 #endif /* not lint */
 
 #ifndef NO_SYSTEM_INCLUDES
@@ -16,11 +16,9 @@ static const char sccsid[] = "@(#)os_stat.c  10.11 (Sleepycat) 1/8/98";
 #include <sys/stat.h>
 
 #include <errno.h>
-#include <string.h>
 #endif
 
 #include "db_int.h"
-#include "common_ext.h"
 
 /*
  * __os_exists --
@@ -37,8 +35,17 @@ __os_exists(path, isdirp)
 
        if (stat(path, &sb) != 0)
                return (errno);
+
+#if !defined(S_ISDIR) || defined(STAT_MACROS_BROKEN)
+#if defined(_WIN32) || defined(WIN16)
+#define        S_ISDIR(m)      (_S_IFDIR & (m))
+#else
+#define        S_ISDIR(m)      (((m) & 0170000) == 0040000)
+#endif
+#endif
        if (isdirp != NULL)
                *isdirp = S_ISDIR(sb.st_mode);
+
        return (0);
 }
 
@@ -69,10 +76,16 @@ __os_ioinfo(path, fd, mbytesp, bytesp, iosizep)
        if (bytesp != NULL)
                *bytesp = sb.st_size % MEGABYTE;
 
-       /* Return the underlying filesystem blocksize, if available. */
+       /*
+        * Return the underlying filesystem blocksize, if available.
+        *
+        * XXX
+        * Check for a 0 size -- HP's MPE architecture has st_blksize,
+        * but it's always 0.
+        */
 #ifdef HAVE_ST_BLKSIZE
-       if (iosizep != NULL)
-               *iosizep = sb.st_blksize;
+       if (iosizep != NULL && (*iosizep = sb.st_blksize) == 0)
+               *iosizep = DB_DEF_IOSIZE;
 #else
        if (iosizep != NULL)
                *iosizep = DB_DEF_IOSIZE;
index 473ce77..3a1fa3f 100644 (file)
@@ -1,14 +1,14 @@
 /*-
  * See the file LICENSE for redistribution information.
  *
- * Copyright (c) 1997
+ * Copyright (c) 1997, 1998
  *     Sleepycat Software.  All rights reserved.
  */
 
 #include "config.h"
 
 #ifndef lint
-static const char sccsid[] = "@(#)os_unlink.c  10.4 (Sleepycat) 10/28/97";
+static const char sccsid[] = "@(#)os_unlink.c  10.5 (Sleepycat) 4/10/98";
 #endif /* not lint */
 
 #ifndef NO_SYSTEM_INCLUDES
index a9c6c28..691824c 100644 (file)
@@ -1,7 +1,7 @@
 /*-
  * See the file LICENSE for redistribution information.
  *
- * Copyright (c) 1996, 1997
+ * Copyright (c) 1996, 1997, 1998
  *     Sleepycat Software.  All rights reserved.
  */
 
@@ -9,9 +9,9 @@
 
 #ifndef lint
 static const char copyright[] =
-"@(#) Copyright (c) 1997\n\
+"@(#) Copyright (c) 1996, 1997, 1998\n\
        Sleepycat Software Inc.  All rights reserved.\n";
-static const char sccsid[] = "@(#)db_archive.c 10.15 (Sleepycat) 8/27/97";
+static const char sccsid[] = "@(#)db_archive.c 10.17 (Sleepycat) 4/10/98";
 #endif
 
 #ifndef NO_SYSTEM_INCLUDES
@@ -50,7 +50,8 @@ main(argc, argv)
        extern char *optarg;
        extern int optind;
        DB_ENV *dbenv;
-       int ch, flags, verbose;
+       u_int32_t flags;
+       int ch, verbose;
        char *home, **list;
 
        flags = verbose = 0;
index 3157a52..74f95cc 100644 (file)
@@ -1,7 +1,7 @@
 /*-
  * See the file LICENSE for redistribution information.
  *
- * Copyright (c) 1996, 1997
+ * Copyright (c) 1996, 1997, 1998
  *     Sleepycat Software.  All rights reserved.
  */
 
@@ -9,9 +9,9 @@
 
 #ifndef lint
 static const char copyright[] =
-"@(#) Copyright (c) 1997\n\
+"@(#) Copyright (c) 1996, 1997, 1998\n\
        Sleepycat Software Inc.  All rights reserved.\n";
-static const char sccsid[] = "@(#)db_checkpoint.c      10.14 (Sleepycat) 1/17/98";
+static const char sccsid[] = "@(#)db_checkpoint.c      10.17 (Sleepycat) 5/3/98";
 #endif
 
 #ifndef NO_SYSTEM_INCLUDES
@@ -37,7 +37,6 @@ static const char sccsid[] = "@(#)db_checkpoint.c     10.14 (Sleepycat) 1/17/98";
 #include "common_ext.h"
 
 char   *check __P((DB_ENV *, long, long));
-int     checkpoint __P((DB_ENV *, char *, int));
 DB_ENV *db_init __P((char *));
 int     logpid __P((char *, int));
 int     main __P((int, char *[]));
@@ -58,26 +57,39 @@ main(argc, argv)
        extern int optind;
        DB_ENV *dbenv;
        time_t now;
-       long kbytes, minutes, seconds;
-       int ch, eval, verbose;
+       long argval;
+       u_int32_t kbytes, minutes, seconds;
+       int ch, eval, once, verbose;
        char *home, *logfile;
 
-       home = logfile = NULL;
+       /*
+        * XXX
+        * Don't allow a fully unsigned 32-bit number, some compilers get
+        * upset and require it to be specified in hexadecimal and so on.
+        */
+#define        MAX_UINT32_T    2147483647
+
        kbytes = minutes = 0;
-       verbose = 0;
-       while ((ch = getopt(argc, argv, "h:k:L:p:v")) != EOF)
+       once = verbose = 0;
+       home = logfile = NULL;
+       while ((ch = getopt(argc, argv, "1h:k:L:p:v")) != EOF)
                switch (ch) {
+               case '1':
+                       once = 1;
+                       break;
                case 'h':
                        home = optarg;
                        break;
                case 'k':
-                       get_long(optarg, 1, LONG_MAX, &kbytes);
+                       get_long(optarg, 1, (long)MAX_UINT32_T, &argval);
+                       kbytes = argval;
                        break;
                case 'L':
                        logfile = optarg;
                        break;
                case 'p':
-                       get_long(optarg, 1, LONG_MAX, &minutes);
+                       get_long(optarg, 1, (long)MAX_UINT32_T, &argval);
+                       minutes = argval;
                        break;
                case 'v':
                        verbose = 1;
@@ -92,8 +104,8 @@ main(argc, argv)
        if (argc != 0)
                usage();
 
-       if (kbytes == 0 && minutes == 0) {
-               warnx("at least one of -k and -p must be specified");
+       if (once == 0 && kbytes == 0 && minutes == 0) {
+               warnx("at least one of -1, -k and -p must be specified");
                usage();
        }
 
@@ -113,8 +125,6 @@ main(argc, argv)
        eval = 0;
        seconds = kbytes != 0 ? 30 : minutes * 60;
        while (!interrupted) {
-               (void)__db_sleep(seconds, 0);
-
                if (verbose) {
                        (void)time(&now);
                        printf("checkpoint: %s", ctime(&now));
@@ -134,6 +144,11 @@ main(argc, argv)
                        __db_err(dbenv, "checkpoint: %s", strerror(errno));
                        break;
                }
+
+               if (once)
+                       break;
+
+               (void)__db_sleep(seconds, 0);
        }
 
        if (logfile != NULL && logpid(logfile, 0))
@@ -244,6 +259,6 @@ void
 usage()
 {
        (void)fprintf(stderr,
-    "usage: db_checkpoint [-v] [-h home] [-k kbytes] [-L file] [-p min]\n");
+    "usage: db_checkpoint [-1v] [-h home] [-k kbytes] [-L file] [-p min]\n");
        exit(1);
 }
index 97fa8ca..49a5241 100644 (file)
@@ -1,7 +1,7 @@
 /*-
  * See the file LICENSE for redistribution information.
  *
- * Copyright (c) 1996, 1997
+ * Copyright (c) 1996, 1997, 1998
  *     Sleepycat Software.  All rights reserved.
  */
 
@@ -9,9 +9,9 @@
 
 #ifndef lint
 static const char copyright[] =
-"@(#) Copyright (c) 1997\n\
+"@(#) Copyright (c) 1996, 1997, 1998\n\
        Sleepycat Software Inc.  All rights reserved.\n";
-static const char sccsid[] = "@(#)db_deadlock.c        10.17 (Sleepycat) 1/15/98";
+static const char sccsid[] = "@(#)db_deadlock.c        10.19 (Sleepycat) 4/10/98";
 #endif
 
 #ifndef NO_SYSTEM_INCLUDES
@@ -54,13 +54,15 @@ main(argc, argv)
        u_int32_t atype;
        time_t now;
        long usecs;
-       int ch, flags, verbose;
+       u_int32_t flags;
+       int ch, verbose;
        char *home, *logfile;
 
        atype = DB_LOCK_DEFAULT;
        home = logfile = NULL;
        usecs = 0;
-       flags = verbose = 0;
+       flags = 0;
+       verbose = 0;
        while ((ch = getopt(argc, argv, "a:h:L:t:vw")) != EOF)
                switch (ch) {
                case 'a':
index c097190..f532bc2 100644 (file)
@@ -1,7 +1,7 @@
 /*-
  * See the file LICENSE for redistribution information.
  *
- * Copyright (c) 1996, 1997
+ * Copyright (c) 1996, 1997, 1998
  *     Sleepycat Software.  All rights reserved.
  */
 
@@ -9,9 +9,9 @@
 
 #ifndef lint
 static const char copyright[] =
-"@(#) Copyright (c) 1997\n\
+"@(#) Copyright (c) 1996, 1997, 1998\n\
        Sleepycat Software Inc.  All rights reserved.\n";
-static const char sccsid[] = "@(#)db_dump.c    10.16 (Sleepycat) 8/27/97";
+static const char sccsid[] = "@(#)db_dump.c    10.19 (Sleepycat) 5/23/98";
 #endif
 
 #ifndef NO_SYSTEM_INCLUDES
@@ -35,8 +35,6 @@ static const char sccsid[] = "@(#)db_dump.c   10.16 (Sleepycat) 8/27/97";
 
 void   configure __P((char *));
 DB_ENV *db_init __P((char *));
-void   dbt_dump __P((DBT *));
-void   dbt_print __P((DBT *));
 int    main __P((int, char *[]));
 void   pheader __P((DB *, int));
 void   usage __P((void));
@@ -55,11 +53,11 @@ main(argc, argv)
        DBC *dbcp;
        DBT key, data;
        DB_ENV *dbenv;
-       int ch, dflag, pflag;
+       int ch, checkprint, dflag;
        char *home;
 
        home = NULL;
-       dflag = pflag = 0;
+       checkprint = dflag = 0;
        while ((ch = getopt(argc, argv, "df:h:p")) != EOF)
                switch (ch) {
                case 'd':
@@ -73,7 +71,7 @@ main(argc, argv)
                        home = optarg;
                        break;
                case 'p':
-                       pflag = 1;
+                       checkprint = 1;
                        break;
                case '?':
                default:
@@ -89,7 +87,7 @@ main(argc, argv)
                if (home != NULL)
                        errx(1,
                            "the -d and -h options may not both be specified");
-               if (pflag)
+               if (checkprint)
                        errx(1,
                            "the -d and -p options may not both be specified");
        }
@@ -116,23 +114,19 @@ main(argc, argv)
        }
 
        /* Print out the header. */
-       pheader(dbp, pflag);
+       pheader(dbp, checkprint);
 
        /* Print out the key/data pairs. */
        memset(&key, 0, sizeof(key));
        memset(&data, 0, sizeof(data));
-       if (pflag)
-               while ((errno = dbcp->c_get(dbcp, &key, &data, DB_NEXT)) == 0) {
-                       if (dbp->type != DB_RECNO)
-                               dbt_print(&key);
-                       dbt_print(&data);
-               }
-       else
-               while ((errno = dbcp->c_get(dbcp, &key, &data, DB_NEXT)) == 0) {
-                       if (dbp->type != DB_RECNO)
-                               dbt_dump(&key);
-                       dbt_dump(&data);
-               }
+       while ((errno = dbcp->c_get(dbcp, &key, &data, DB_NEXT)) == 0) {
+               if (dbp->type != DB_RECNO &&
+                   (errno = __db_prdbt(&key, checkprint, stdout)) != 0)
+                       break;
+               if ((errno = __db_prdbt(&data, checkprint, stdout)) != 0)
+                       break;
+       }
+
        if (errno != DB_NOTFOUND)
                err(1, "cursor get");
 
@@ -229,47 +223,6 @@ pheader(dbp, pflag)
        printf("HEADER=END\n");
 }
 
-static char hex[] = "0123456789abcdef";
-
-/*
- * dbt_dump --
- *     Write out a key or data item using byte values.
- */
-void
-dbt_dump(dbtp)
-       DBT *dbtp;
-{
-       u_int32_t len;
-       u_int8_t *p;
-
-       for (len = dbtp->size, p = dbtp->data; len--; ++p)
-               (void)printf("%c%c",
-                   hex[(u_int8_t)(*p & 0xf0) >> 4], hex[*p & 0x0f]);
-       printf("\n");
-}
-
-/*
- * dbt_print --
- *     Write out a key or data item using printable characters.
- */
-void
-dbt_print(dbtp)
-       DBT *dbtp;
-{
-       u_int32_t len;
-       u_int8_t *p;
-
-       for (len = dbtp->size, p = dbtp->data; len--; ++p)
-               if (isprint(*p)) {
-                       if (*p == '\\')
-                               (void)printf("\\");
-                       (void)printf("%c", *p);
-               } else
-                       (void)printf("\\%c%c",
-                           hex[(u_int8_t)(*p & 0xf0) >> 4], hex[*p & 0x0f]);
-       printf("\n");
-}
-
 /*
  * usage --
  *     Display the usage message.
index 5ec7673..1745110 100644 (file)
@@ -1,7 +1,7 @@
 /*-
  * See the file LICENSE for redistribution information.
  *
- * Copyright (c) 1996, 1997
+ * Copyright (c) 1996, 1997, 1998
  *     Sleepycat Software.  All rights reserved.
  */
 
@@ -9,9 +9,9 @@
 
 #ifndef lint
 static const char copyright[] =
-"@(#) Copyright (c) 1997\n\
+"@(#) Copyright (c) 1996, 1997, 1998\n\
        Sleepycat Software Inc.  All rights reserved.\n";
-static const char sccsid[] = "@(#)db_dump185.c 10.8 (Sleepycat) 9/21/97";
+static const char sccsid[] = "@(#)db_dump185.c 10.10 (Sleepycat) 4/10/98";
 #endif
 
 #ifndef NO_SYSTEM_INCLUDES
@@ -30,7 +30,7 @@ static const char sccsid[] = "@(#)db_dump185.c        10.8 (Sleepycat) 9/21/97";
 #include "clib_ext.h"
 
 /* Hash Table Information */
-typedef struct hashhdr {               /* Disk resident portion */
+typedef struct hashhdr185 {            /* Disk resident portion */
        int             magic;          /* Magic NO for hash tables */
        int             version;        /* Version ID */
        u_int32_t       lorder;         /* Byte Order */
@@ -48,11 +48,34 @@ typedef struct hashhdr {            /* Disk resident portion */
                                         * table */
        int             ffactor;        /* Fill factor */
        int             nkeys;          /* Number of keys in hash table */
-} HASHHDR;
+} HASHHDR185;
+typedef struct htab185  {              /* Memory resident data structure */
+       HASHHDR185      hdr;            /* Header */
+} HTAB185;
 
-typedef struct htab     {              /* Memory resident data structure */
-       HASHHDR         hdr;            /* Header */
-} HTAB;
+/* Hash Table Information */
+typedef struct hashhdr186 {    /* Disk resident portion */
+       int32_t magic;          /* Magic NO for hash tables */
+       int32_t version;        /* Version ID */
+       int32_t lorder;         /* Byte Order */
+       int32_t bsize;          /* Bucket/Page Size */
+       int32_t bshift;         /* Bucket shift */
+       int32_t ovfl_point;     /* Where overflow pages are being allocated */
+       int32_t last_freed;     /* Last overflow page freed */
+       int32_t max_bucket;     /* ID of Maximum bucket in use */
+       int32_t high_mask;      /* Mask to modulo into entire table */
+       int32_t low_mask;       /* Mask to modulo into lower half of table */
+       int32_t ffactor;        /* Fill factor */
+       int32_t nkeys;          /* Number of keys in hash table */
+       int32_t hdrpages;       /* Size of table header */
+       int32_t h_charkey;      /* value of hash(CHARKEY) */
+#define NCACHED        32              /* number of bit maps and spare points */
+       int32_t spares[NCACHED];/* spare pages for overflow */
+       u_int16_t       bitmaps[NCACHED];       /* address of overflow page bitmaps */
+} HASHHDR186;
+typedef struct htab186  {              /* Memory resident data structure */
+       HASHHDR186      hdr;            /* Header */
+} HTAB186;
 
 typedef struct _epgno {
        u_int32_t pgno;                 /* the page number */
@@ -149,8 +172,8 @@ typedef struct _btree {
        u_int32_t flags;
 } BTREE;
 
-void   db_185_btree __P((DB *, int));
-void   db_185_hash __P((DB *, int));
+void   db_btree __P((DB *, int));
+void   db_hash __P((DB *, int));
 void   dbt_dump __P((DBT *));
 void   dbt_print __P((DBT *));
 int    main __P((int, char *[]));
@@ -193,9 +216,9 @@ main(argc, argv)
        if ((dbp = dbopen(argv[0], O_RDONLY, 0, DB_BTREE, NULL)) == NULL) {
                if ((dbp = dbopen(argv[0], O_RDONLY, 0, DB_HASH, NULL)) == NULL)
                        err(1, "%s", argv[0]);
-               db_185_hash(dbp, pflag);
+               db_hash(dbp, pflag);
        } else
-               db_185_btree(dbp, pflag);
+               db_btree(dbp, pflag);
 
        /*
         * !!!
@@ -219,36 +242,43 @@ main(argc, argv)
 }
 
 /*
- * db_185_hash --
+ * db_hash --
  *     Dump out hash header information.
  */
 void
-db_185_hash(dbp, pflag)
+db_hash(dbp, pflag)
        DB *dbp;
        int pflag;
 {
-       HTAB *hashp;
-
-       hashp = dbp->internal;
+       HTAB185 *hash185p;
+       HTAB186 *hash186p;
 
        printf("format=%s\n", pflag ? "print" : "bytevalue");
        printf("type=hash\n");
-       printf("h_ffactor=%lu\n", (u_long)hashp->hdr.ffactor);
-#ifdef NOT_AVAILABLE_IN_DB_185
-       printf("h_nelem=%lu\n", (u_long)hashp->hdr.nelem);
-#endif
-       if (hashp->hdr.lorder != 0)
-               printf("db_lorder=%lu\n", (u_long)hashp->hdr.lorder);
-       printf("db_pagesize=%lu\n", (u_long)hashp->hdr.bsize);
+
+       /* DB 1.85 was version 2, DB 1.86 was version 3. */
+       hash185p = dbp->internal;
+       if (hash185p->hdr.version > 2) {
+               hash186p = dbp->internal;
+               printf("h_ffactor=%lu\n", (u_long)hash186p->hdr.ffactor);
+               if (hash186p->hdr.lorder != 0)
+                       printf("db_lorder=%lu\n", (u_long)hash186p->hdr.lorder);
+               printf("db_pagesize=%lu\n", (u_long)hash186p->hdr.bsize);
+       } else {
+               printf("h_ffactor=%lu\n", (u_long)hash185p->hdr.ffactor);
+               if (hash185p->hdr.lorder != 0)
+                       printf("db_lorder=%lu\n", (u_long)hash185p->hdr.lorder);
+               printf("db_pagesize=%lu\n", (u_long)hash185p->hdr.bsize);
+       }
        printf("HEADER=END\n");
 }
 
 /*
- * db_185_btree --
+ * db_btree --
  *     Dump out btree header information.
  */
 void
-db_185_btree(dbp, pflag)
+db_btree(dbp, pflag)
        DB *dbp;
        int pflag;
 {
index afa5730..5ac1775 100644 (file)
@@ -1,7 +1,7 @@
 /*-
  * See the file LICENSE for redistribution information.
  *
- * Copyright (c) 1996, 1997
+ * Copyright (c) 1996, 1997, 1998
  *     Sleepycat Software.  All rights reserved.
  */
 
@@ -9,14 +9,13 @@
 
 #ifndef lint
 static const char copyright[] =
-"@(#) Copyright (c) 1997\n\
+"@(#) Copyright (c) 1996, 1997, 1998\n\
        Sleepycat Software Inc.  All rights reserved.\n";
-static const char sccsid[] = "@(#)db_load.c    10.15 (Sleepycat) 12/29/97";
+static const char sccsid[] = "@(#)db_load.c    10.20 (Sleepycat) 6/2/98";
 #endif
 
 #ifndef NO_SYSTEM_INCLUDES
 #include <sys/types.h>
-#include <sys/stat.h>
 
 #include <errno.h>
 #include <limits.h>
@@ -27,6 +26,8 @@ static const char sccsid[] = "@(#)db_load.c   10.15 (Sleepycat) 12/29/97";
 #endif
 
 #include "db_int.h"
+#include "db_page.h"
+#include "db_am.h"
 #include "clib_ext.h"
 
 void   badnum __P((void));
@@ -55,7 +56,8 @@ main(argc, argv)
        DB_ENV *dbenv;
        DB_INFO dbinfo;
        db_recno_t recno;
-       int ch, no_header, pflag;
+       u_int32_t db_nooverwrite;
+       int ch, checkprint, existed, no_header;
        char **clist, **clp, *home;
 
        /* Allocate enough room for configuration arguments. */
@@ -63,9 +65,10 @@ main(argc, argv)
                err(1, NULL);
 
        home = NULL;
-       no_header = 0;
+       db_nooverwrite = 0;
+       existed = checkprint = no_header = 0;
        argtype = dbtype = DB_UNKNOWN;
-       while ((ch = getopt(argc, argv, "c:f:h:Tt:")) != EOF)
+       while ((ch = getopt(argc, argv, "c:f:h:nTt:")) != EOF)
                switch (ch) {
                case 'c':
                        *clp++ = optarg;
@@ -77,8 +80,11 @@ main(argc, argv)
                case 'h':
                        home = optarg;
                        break;
+               case 'n':
+                       db_nooverwrite = DB_NOOVERWRITE;
+                       break;
                case 'T':
-                       no_header = pflag = 1;
+                       no_header = checkprint = 1;
                        break;
                case 't':
                        if (strcmp(optarg, "btree") == 0) {
@@ -105,18 +111,18 @@ main(argc, argv)
        if (argc != 1)
                usage();
 
-       /* Initialize the environment. */
-       dbenv = db_init(home);
-       memset(&dbinfo, 0, sizeof(DB_INFO));
+       /* Initialize the environment if the user specified one. */
+       dbenv = home == NULL ? NULL : db_init(home);
 
        /*
         * Read the header.  If there isn't any header, we're expecting flat
-        * text, set the pflag appropriately.
+        * text, set the checkprint flag appropriately.
         */
+       memset(&dbinfo, 0, sizeof(DB_INFO));
        if (no_header)
                dbtype = argtype;
        else {
-               rheader(&dbtype, &pflag, &dbinfo);
+               rheader(&dbtype, &checkprint, &dbinfo);
                if (argtype != DB_UNKNOWN) {
                        /* Conversion to/from recno is prohibited. */
                        if ((dbtype == DB_RECNO && argtype != DB_RECNO) ||
@@ -133,17 +139,20 @@ main(argc, argv)
        configure(&dbinfo, clist);
 
        /* Open the DB file. */
-       if ((errno = db_open(argv[0], dbtype, DB_CREATE | DB_TRUNCATE,
-           S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH,
-           dbenv, &dbinfo, &dbp)) != 0)
+       if ((errno = db_open(argv[0], dbtype, DB_CREATE,
+           __db_omode("rwrwrw"), dbenv, &dbinfo, &dbp)) != 0)
                err(1, "%s", argv[0]);
 
        /* Initialize the key/data pair. */
        memset(&key, 0, sizeof(DBT));
-       if ((key.data = (void *)malloc(key.ulen = 1024)) == NULL) {
-               errno = ENOMEM;
-               err(1, NULL);
-       }
+       if (dbtype == DB_RECNO) {
+               key.data = &recno;
+               key.size = sizeof(recno);
+       } else
+               if ((key.data = (void *)malloc(key.ulen = 1024)) == NULL) {
+                       errno = ENOMEM;
+                       err(1, NULL);
+               }
        memset(&data, 0, sizeof(DBT));
        if ((data.data = (void *)malloc(data.ulen = 1024)) == NULL) {
                errno = ENOMEM;
@@ -151,22 +160,17 @@ main(argc, argv)
        }
 
        /* Get each key/data pair and add them to the database. */
-       if (dbtype == DB_RECNO) {
-               key.data = &recno;
-               key.size = sizeof(recno);
-               for (recno = 1;; ++recno) {
-                       if (pflag) {
+       for (recno = 1;; ++recno) {
+               if (dbtype == DB_RECNO)
+                       if (checkprint) {
                                if (dbt_rprint(&data))
                                        break;
-                       } else
+                       } else {
                                if (dbt_rdump(&data))
                                        break;
-                       if ((errno = dbp->put(dbp, NULL, &key, &data, 0)) != 0)
-                               err(1, "%s", argv[0]);
-               }
-       } else
-               for (;;) {
-                       if (pflag) {
+                       }
+               else
+                       if (checkprint) {
                                if (dbt_rprint(&key))
                                        break;
                                if (dbt_rprint(&data))
@@ -177,13 +181,26 @@ main(argc, argv)
                                if (dbt_rdump(&data))
 fmt:                                   err(1, "odd number of key/data pairs");
                        }
-                       if ((errno = dbp->put(dbp, NULL, &key, &data, 0)) != 0)
-                               err(1, "%s", argv[0]);
+               switch (errno =
+                   dbp->put(dbp, NULL, &key, &data, db_nooverwrite)) {
+               case 0:
+                       break;
+               case DB_KEYEXIST:
+                       existed = 1;
+                       warnx("%s: line %d: key already exists, not loaded:",
+                           argv[0],
+                           dbtype == DB_RECNO ? recno : recno * 2 - 1);
+                       (void)__db_prdbt(&key, checkprint, stderr);
+                       break;
+               default:
+                       err(1, "%s", argv[0]);
+                       /* NOTREACHED */
                }
+       }
 
        if ((errno = dbp->close(dbp, 0)) != 0)
                err(1, "%s", argv[0]);
-       return (0);
+       return (existed ? 1 : 0);
 }
 
 /*
@@ -200,13 +217,26 @@ db_init(home)
                errno = ENOMEM;
                err(1, NULL);
        }
-       dbenv->db_errfile = stderr;
-       dbenv->db_errpfx = progname;
 
-       if ((errno =
-           db_appinit(home, NULL, dbenv, DB_CREATE | DB_USE_ENVIRON)) != 0)
-               err(1, "db_appinit");
-       return (dbenv);
+       /*
+        * The database may be live, try and use the shared regions.
+        *
+        * If it works, we're done.  Set the error output options so that
+        * future errors are correctly reported.
+        */
+       if ((errno = db_appinit(home, NULL, dbenv, DB_INIT_LOCK |
+           DB_INIT_LOG | DB_INIT_MPOOL | DB_INIT_TXN | DB_USE_ENVIRON)) == 0) {
+               dbenv->db_errfile = stderr;
+               dbenv->db_errpfx = progname;
+               return (dbenv);
+       }
+
+       /*
+        * If the db_appinit fails, assume the database isn't live, and don't
+        * bother with an environment.
+        */
+       free(dbenv);
+       return (NULL);
 }
 
 #define        FLAG(name, value, keyword, flag)                                \
@@ -279,16 +309,16 @@ configure(dbinfop, clp)
  *     Read the header message.
  */
 void
-rheader(dbtypep, pflagp, dbinfop)
+rheader(dbtypep, checkprintp, dbinfop)
        DBTYPE *dbtypep;
-       int *pflagp;
+       int *checkprintp;
        DB_INFO *dbinfop;
 {
        long lineno, val;
        char name[256], value[256];
 
        *dbtypep = DB_UNKNOWN;
-       *pflagp = 0;
+       *checkprintp = 0;
 
        for (lineno = 1;; ++lineno) {
                /* If we don't see the expected information, it's an error. */
@@ -301,11 +331,11 @@ rheader(dbtypep, pflagp, dbinfop)
 
                if (strcmp(name, "format") == 0) {
                        if (strcmp(value, "bytevalue") == 0) {
-                               *pflagp = 0;
+                               *checkprintp = 0;
                                continue;
                        }
                        if (strcmp(value, "print") == 0) {
-                               *pflagp = 1;
+                               *checkprintp = 1;
                                continue;
                        }
                        errx(1, "line %d: unknown format", lineno);
@@ -390,39 +420,6 @@ dbt_rprint(dbtp)
 }
 
 /*
- * digitize --
- *     Convert a character to an integer.
- */
-int
-digitize(c)
-       int c;
-{
-       switch (c) {                    /* Don't depend on ASCII ordering. */
-       case '0': return (0);
-       case '1': return (1);
-       case '2': return (2);
-       case '3': return (3);
-       case '4': return (4);
-       case '5': return (5);
-       case '6': return (6);
-       case '7': return (7);
-       case '8': return (8);
-       case '9': return (9);
-       case 'a': return (10);
-       case 'b': return (11);
-       case 'c': return (12);
-       case 'd': return (13);
-       case 'e': return (14);
-       case 'f': return (15);
-       }
-
-       err(1, "unexpected hexadecimal value");
-       /* NOTREACHED */
-
-       return (0);
-}
-
-/*
  * dbt_rdump --
  *     Read a byte dump line into a DBT structure.
  */
@@ -459,6 +456,39 @@ dbt_rdump(dbtp)
 }
 
 /*
+ * digitize --
+ *     Convert a character to an integer.
+ */
+int
+digitize(c)
+       int c;
+{
+       switch (c) {                    /* Don't depend on ASCII ordering. */
+       case '0': return (0);
+       case '1': return (1);
+       case '2': return (2);
+       case '3': return (3);
+       case '4': return (4);
+       case '5': return (5);
+       case '6': return (6);
+       case '7': return (7);
+       case '8': return (8);
+       case '9': return (9);
+       case 'a': return (10);
+       case 'b': return (11);
+       case 'c': return (12);
+       case 'd': return (13);
+       case 'e': return (14);
+       case 'f': return (15);
+       }
+
+       err(1, "unexpected hexadecimal value");
+       /* NOTREACHED */
+
+       return (0);
+}
+
+/*
  * badnum --
  *     Display the bad number message.
  */
@@ -475,7 +505,8 @@ badnum()
 void
 usage()
 {
-       (void)fprintf(stderr,
-"usage: db_load [-T]\n\t[-c name=value] [-f file] [-h home] [-t btree | hash] db_file\n");
+       (void)fprintf(stderr, "%s\n\t%s\n",
+           "usage: db_load [-nT]",
+    "[-c name=value] [-f file] [-h home] [-t btree | hash | recno] db_file");
        exit(1);
 }
index 24554bc..3b48ad9 100644 (file)
@@ -1,7 +1,7 @@
 /*-
  * See the file LICENSE for redistribution information.
  *
- * Copyright (c) 1996, 1997
+ * Copyright (c) 1996, 1997, 1998
  *     Sleepycat Software.  All rights reserved.
  */
 
@@ -9,9 +9,9 @@
 
 #ifndef lint
 static const char copyright[] =
-"@(#) Copyright (c) 1997\n\
+"@(#) Copyright (c) 1996, 1997, 1998\n\
        Sleepycat Software Inc.  All rights reserved.\n";
-static const char sccsid[] = "@(#)db_printlog.c        10.11 (Sleepycat) 1/8/98";
+static const char sccsid[] = "@(#)db_printlog.c        10.12 (Sleepycat) 4/10/98";
 #endif
 
 #ifndef NO_SYSTEM_INCLUDES
index f902fed..a284572 100644 (file)
@@ -1,7 +1,7 @@
 /*-
  * See the file LICENSE for redistribution information.
  *
- * Copyright (c) 1996, 1997
+ * Copyright (c) 1996, 1997, 1998
  *     Sleepycat Software.  All rights reserved.
  */
 
@@ -9,9 +9,9 @@
 
 #ifndef lint
 static const char copyright[] =
-"@(#) Copyright (c) 1997\n\
+"@(#) Copyright (c) 1996, 1997, 1998\n\
        Sleepycat Software Inc.  All rights reserved.\n";
-static const char sccsid[] = "@(#)db_recover.c 10.17 (Sleepycat) 1/15/98";
+static const char sccsid[] = "@(#)db_recover.c 10.19 (Sleepycat) 4/10/98";
 #endif
 
 #ifndef NO_SYSTEM_INCLUDES
@@ -29,7 +29,7 @@ static const char sccsid[] = "@(#)db_recover.c        10.17 (Sleepycat) 1/15/98";
 #include "common_ext.h"
 #include "clib_ext.h"
 
-DB_ENV *db_init __P((char *, int, int));
+DB_ENV *db_init __P((char *, u_int32_t, int));
 int     main __P((int, char *[]));
 void    usage __P((void));
 
@@ -45,7 +45,8 @@ main(argc, argv)
        extern int optind;
        DB_ENV *dbenv;
        time_t now;
-       int ch, flags, verbose;
+       u_int32_t flags;
+       int ch, verbose;
        char *home;
 
        home = NULL;
@@ -88,10 +89,11 @@ main(argc, argv)
 DB_ENV *
 db_init(home, flags, verbose)
        char *home;
-       int flags, verbose;
+       u_int32_t flags;
+       int verbose;
 {
        DB_ENV *dbenv;
-       int local_flags;
+       u_int32_t local_flags;
 
        if ((dbenv = (DB_ENV *)calloc(sizeof(DB_ENV), 1)) == NULL) {
                errno = ENOMEM;
index 5295f01..f255180 100644 (file)
@@ -1,7 +1,7 @@
 /*-
  * See the file LICENSE for redistribution information.
  *
- * Copyright (c) 1996, 1997
+ * Copyright (c) 1996, 1997, 1998
  *     Sleepycat Software.  All rights reserved.
  */
 
@@ -9,9 +9,9 @@
 
 #ifndef lint
 static const char copyright[] =
-"@(#) Copyright (c) 1997\n\
+"@(#) Copyright (c) 1996, 1997, 1998\n\
        Sleepycat Software Inc.  All rights reserved.\n";
-static const char sccsid[] = "@(#)db_stat.c    8.30 (Sleepycat) 1/8/98";
+static const char sccsid[] = "@(#)db_stat.c    8.38 (Sleepycat) 5/30/98";
 #endif
 
 #ifndef NO_SYSTEM_INCLUDES
@@ -27,25 +27,35 @@ static const char sccsid[] = "@(#)db_stat.c 8.30 (Sleepycat) 1/8/98";
 #endif
 
 #include "db_int.h"
+#include "shqueue.h"
+#include "db_shash.h"
+#include "lock.h"
+#include "mp.h"
 #include "clib_ext.h"
 
 #undef stat
 
-typedef enum { T_NOTSET, T_DB, T_LOG, T_MPOOL, T_TXN } test_t;
+typedef enum { T_NOTSET, T_DB, T_LOCK, T_LOG, T_MPOOL, T_TXN } test_t;
 
+int    argcheck __P((char *, const char *));
 void   btree_stats __P((DB *));
 DB_ENV *db_init __P((char *, test_t));
+void   dl __P((const char *, u_long));
 void   hash_stats __P((DB *));
-int    main __P((int, char *[]));
+int    lock_ok __P((char *));
+void   lock_stats __P((DB_ENV *));
 void   log_stats __P((DB_ENV *));
+int    main __P((int, char *[]));
+int    mpool_ok __P((char *));
 void   mpool_stats __P((DB_ENV *));
 void   onint __P((int));
 void   prflags __P((u_int32_t, const FN *));
-void   txn_stats __P((DB_ENV *));
 int    txn_compare __P((const void *, const void *));
+void   txn_stats __P((DB_ENV *));
 void   usage __P((void));
 
 int     interrupted;
+char   *internal;
 const char
        *progname = "db_stat";                          /* Program name. */
 
@@ -64,8 +74,16 @@ main(argc, argv)
 
        ttype = T_NOTSET;
        db = home = NULL;
-       while ((ch = getopt(argc, argv, "d:h:lmt")) != EOF)
+       while ((ch = getopt(argc, argv, "C:cd:h:lM:mNt")) != EOF)
                switch (ch) {
+               case 'C':
+                       ttype = T_LOCK;
+                       if (!argcheck(internal = optarg, "Acflmo"))
+                               usage();
+                       break;
+               case 'c':
+                       ttype = T_LOCK;
+                       break;
                case 'd':
                        db = optarg;
                        ttype = T_DB;
@@ -76,9 +94,17 @@ main(argc, argv)
                case 'l':
                        ttype = T_LOG;
                        break;
+               case 'M':
+                       ttype = T_MPOOL;
+                       if (!argcheck(internal = optarg, "Ahlm"))
+                               usage();
+                       break;
                case 'm':
                        ttype = T_MPOOL;
                        break;
+               case 'N':
+                       (void)db_value_set(0, DB_MUTEXLOCKS);
+                       break;
                case 't':
                        ttype = T_TXN;
                        break;
@@ -115,6 +141,9 @@ main(argc, argv)
                }
                (void)dbp->close(dbp, 0);
                break;
+       case T_LOCK:
+               lock_stats(dbenv);
+               break;
        case T_LOG:
                log_stats(dbenv);
                break;
@@ -168,13 +197,12 @@ btree_stats(dbp)
        prflags(sp->bt_flags, fn);
        if (dbp->type == DB_BTREE) {
 #ifdef NOT_IMPLEMENTED
-               printf("%lu\tMaximum keys per-page.\n", (u_long)sp->bt_maxkey);
+               dl("Maximum keys per-page.\n", (u_long)sp->bt_maxkey);
 #endif
-               printf("%lu\tMinimum keys per-page.\n", (u_long)sp->bt_minkey);
+               dl("Minimum keys per-page.\n", (u_long)sp->bt_minkey);
        }
        if (dbp->type == DB_RECNO) {
-               printf("%lu\tFixed-length record size.\n",
-                   (u_long)sp->bt_re_len);
+               dl("Fixed-length record size.\n", (u_long)sp->bt_re_len);
                if (isprint(sp->bt_re_pad))
                        printf("%c\tFixed-length record pad.\n",
                            (int)sp->bt_re_pad);
@@ -182,43 +210,38 @@ btree_stats(dbp)
                        printf("0x%x\tFixed-length record pad.\n",
                            (int)sp->bt_re_pad);
        }
-       printf("%lu\tUnderlying tree page size.\n", (u_long)sp->bt_pagesize);
-       printf("%lu\tNumber of levels in the tree.\n", (u_long)sp->bt_levels);
-       printf("%lu\tNumber of keys in the tree.\n", (u_long)sp->bt_nrecs);
-       printf("%lu\tNumber of tree internal pages.\n", (u_long)sp->bt_int_pg);
-       printf("%lu\tNumber of tree leaf pages.\n", (u_long)sp->bt_leaf_pg);
-       printf("%lu\tNumber of tree duplicate pages.\n",
-           (u_long)sp->bt_dup_pg);
-       printf("%lu\tNumber of tree overflow pages.\n",
-           (u_long)sp->bt_over_pg);
-       printf("%lu\tNumber of pages on the free list.\n",
-           (u_long)sp->bt_free);
-       printf("%lu\tNumber of pages freed for reuse.\n",
-           (u_long)sp->bt_freed);
-       printf("%lu\tNumber of bytes free in tree internal pages (%.0f%% ff)\n",
-           (u_long)sp->bt_int_pgfree,
-           PCT(sp->bt_int_pgfree, sp->bt_int_pg));
-       printf("%lu\tNumber of bytes free in tree leaf pages (%.0f%% ff).\n",
-           (u_long)sp->bt_leaf_pgfree,
-           PCT(sp->bt_leaf_pgfree, sp->bt_leaf_pg));
-printf("%lu\tNumber of bytes free in tree duplicate pages (%.0f%% ff).\n",
-           (u_long)sp->bt_dup_pgfree,
-           PCT(sp->bt_dup_pgfree, sp->bt_dup_pg));
-printf("%lu\tNumber of bytes free in tree overflow pages (%.0f%% ff).\n",
-           (u_long)sp->bt_over_pgfree,
-           PCT(sp->bt_over_pgfree, sp->bt_over_pg));
-       printf("%lu\tNumber of bytes saved by prefix compression.\n",
+       dl("Underlying tree page size.\n", (u_long)sp->bt_pagesize);
+       dl("Number of levels in the tree.\n", (u_long)sp->bt_levels);
+       dl("Number of keys in the tree.\n", (u_long)sp->bt_nrecs);
+       dl("Number of tree internal pages.\n", (u_long)sp->bt_int_pg);
+       dl("Number of tree leaf pages.\n", (u_long)sp->bt_leaf_pg);
+       dl("Number of tree duplicate pages.\n", (u_long)sp->bt_dup_pg);
+       dl("Number of tree overflow pages.\n", (u_long)sp->bt_over_pg);
+       dl("Number of pages on the free list.\n", (u_long)sp->bt_free);
+       dl("Number of pages freed for reuse.\n", (u_long)sp->bt_freed);
+       dl("Number of bytes free in tree internal pages",
+           (u_long)sp->bt_int_pgfree);
+       printf(" (%.0f%% ff).\n", PCT(sp->bt_int_pgfree, sp->bt_int_pg));
+       dl("Number of bytes free in tree leaf pages",
+           (u_long)sp->bt_leaf_pgfree);
+       printf(" (%.0f%% ff).\n", PCT(sp->bt_leaf_pgfree, sp->bt_leaf_pg));
+       dl("Number of bytes free in tree duplicate pages",
+           (u_long)sp->bt_dup_pgfree);
+       printf(" (%.0f%% ff).\n", PCT(sp->bt_dup_pgfree, sp->bt_dup_pg));
+       dl("Number of bytes free in tree overflow pages",
+           (u_long)sp->bt_over_pgfree);
+       printf(" (%.0f%% ff).\n", PCT(sp->bt_over_pgfree, sp->bt_over_pg));
+       dl("Number of bytes saved by prefix compression.\n",
            (u_long)sp->bt_pfxsaved);
-       printf("%lu\tTotal number of tree page splits.\n",
-           (u_long)sp->bt_split);
-       printf("%lu\tNumber of root page splits.\n", (u_long)sp->bt_rootsplit);
-       printf("%lu\tNumber of fast splits.\n", (u_long)sp->bt_fastsplit);
-       printf("%lu\tNumber of hits in tree fast-insert code.\n",
+       dl("Total number of tree page splits.\n", (u_long)sp->bt_split);
+       dl("Number of root page splits.\n", (u_long)sp->bt_rootsplit);
+       dl("Number of fast splits.\n", (u_long)sp->bt_fastsplit);
+       dl("Number of hits in tree fast-insert code.\n",
            (u_long)sp->bt_cache_hit);
-       printf("%lu\tNumber of misses in tree fast-insert code.\n",
+       dl("Number of misses in tree fast-insert code.\n",
            (u_long)sp->bt_cache_miss);
-       printf("%lu\tNumber of keys added.\n", (u_long)sp->bt_added);
-       printf("%lu\tNumber of keys deleted.\n", (u_long)sp->bt_deleted);
+       dl("Number of keys added.\n", (u_long)sp->bt_added);
+       dl("Number of keys deleted.\n", (u_long)sp->bt_deleted);
 }
 
 /*
@@ -231,10 +254,47 @@ hash_stats(dbp)
 {
        COMPQUIET(dbp, NULL);
 
+       printf("Hash statistics not currently available.\n");
        return;
 }
 
 /*
+ * lock_stats --
+ *     Display lock statistics.
+ */
+void
+lock_stats(dbenv)
+       DB_ENV *dbenv;
+{
+       DB_LOCK_STAT *sp;
+
+       if (internal != NULL) {
+               __lock_dump_region(dbenv->lk_info, internal, stdout);
+               return;
+       }
+
+       if (lock_stat(dbenv->lk_info, &sp, NULL))
+               err(1, NULL);
+
+       printf("%#lx\tLock magic number.\n", (u_long)sp->st_magic);
+       printf("%lu\tLock version number.\n", (u_long)sp->st_version);
+       dl("Lock region reference count.\n", (u_long)sp->st_refcnt);
+       dl("Lock region size.\n", (u_long)sp->st_regsize);
+       dl("Maximum number of locks.\n", (u_long)sp->st_maxlocks);
+       dl("Number of lock modes.\n", (u_long)sp->st_nmodes);
+       dl("Number of lock objects.\n", (u_long)sp->st_numobjs);
+       dl("Number of lockers.\n", (u_long)sp->st_nlockers);
+       dl("Number of lock conflicts.\n", (u_long)sp->st_nconflicts);
+       dl("Number of lock requests.\n", (u_long)sp->st_nrequests);
+       dl("Number of lock releases.\n", (u_long)sp->st_nreleases);
+       dl("Number of deadlocks.\n", (u_long)sp->st_ndeadlocks);
+       dl("The number of region locks granted without waiting.\n",
+           (u_long)sp->st_region_nowait);
+       dl("The number of region locks granted after waiting.\n",
+           (u_long)sp->st_region_wait);
+}
+
+/*
  * log_stats --
  *     Display log statistics.
  */
@@ -249,6 +309,8 @@ log_stats(dbenv)
 
        printf("%#lx\tLog magic number.\n", (u_long)sp->st_magic);
        printf("%lu\tLog version number.\n", (u_long)sp->st_version);
+       dl("Log region reference count.\n", (u_long)sp->st_refcnt);
+       dl("Log region size.\n", (u_long)sp->st_regsize);
        printf("%#o\tLog file mode.\n", sp->st_mode);
        if (sp->st_lg_max % MEGABYTE == 0)
                printf("%luMb\tLog file size.\n",
@@ -261,13 +323,13 @@ log_stats(dbenv)
            (u_long)sp->st_w_mbytes, (u_long)sp->st_w_bytes);
        printf("%luMb\tLog bytes written since last checkpoint (+%lu bytes).\n",
            (u_long)sp->st_wc_mbytes, (u_long)sp->st_wc_bytes);
-       printf("%lu\tTotal log file writes.\n", (u_long)sp->st_wcount);
-       printf("%lu\tTotal log file flushes.\n", (u_long)sp->st_scount);
+       dl("Total log file writes.\n", (u_long)sp->st_wcount);
+       dl("Total log file flushes.\n", (u_long)sp->st_scount);
        printf("%lu\tCurrent log file number.\n", (u_long)sp->st_cur_file);
        printf("%lu\tCurrent log file offset.\n", (u_long)sp->st_cur_offset);
-       printf("%lu\tThe number of region locks granted without waiting.\n",
+       dl("The number of region locks granted without waiting.\n",
            (u_long)sp->st_region_nowait);
-       printf("%lu\tThe number of region locks granted after waiting.\n",
+       dl("The number of region locks granted after waiting.\n",
            (u_long)sp->st_region_wait);
 }
 
@@ -282,70 +344,74 @@ mpool_stats(dbenv)
        DB_MPOOL_FSTAT **fsp;
        DB_MPOOL_STAT *gsp;
 
+       if (internal != NULL) {
+               __memp_dump_region(dbenv->mp_info, internal, stdout);
+               return;
+       }
+
        if (memp_stat(dbenv->mp_info, &gsp, &fsp, NULL))
                err(1, NULL);
 
-       printf("%lu\tCache size (%luK).\n",
-           (u_long)gsp->st_cachesize, (u_long)gsp->st_cachesize / 1024);
-       printf("%lu\tRequested pages found in the cache",
-           (u_long)gsp->st_cache_hit);
+       dl("Pool region reference count.\n", (u_long)gsp->st_refcnt);
+       dl("Pool region size.\n", (u_long)gsp->st_regsize);
+       dl("Cache size", (u_long)gsp->st_cachesize);
+       printf(" (%luK).\n", (u_long)gsp->st_cachesize / 1024);
+       dl("Requested pages found in the cache", (u_long)gsp->st_cache_hit);
        if (gsp->st_cache_hit + gsp->st_cache_miss != 0)
                printf(" (%.0f%%)", ((double)gsp->st_cache_hit /
                    (gsp->st_cache_hit + gsp->st_cache_miss)) * 100);
        printf(".\n");
-       printf("%lu\tRequested pages mapped into the process' address space.\n",
+       dl("Requested pages mapped into the process' address space.\n",
            (u_long)gsp->st_map);
-       printf("%lu\tRequested pages not found in the cache.\n",
+       dl("Requested pages not found in the cache.\n",
            (u_long)gsp->st_cache_miss);
-       printf("%lu\tPages created in the cache.\n",
-           (u_long)gsp->st_page_create);
-       printf("%lu\tPages read into the cache.\n", (u_long)gsp->st_page_in);
-       printf("%lu\tPages written from the cache to the backing file.\n",
+       dl("Pages created in the cache.\n", (u_long)gsp->st_page_create);
+       dl("Pages read into the cache.\n", (u_long)gsp->st_page_in);
+       dl("Pages written from the cache to the backing file.\n",
            (u_long)gsp->st_page_out);
-       printf("%lu\tClean pages forced from the cache.\n",
+       dl("Clean pages forced from the cache.\n",
            (u_long)gsp->st_ro_evict);
-       printf("%lu\tDirty pages forced from the cache.\n",
+       dl("Dirty pages forced from the cache.\n",
            (u_long)gsp->st_rw_evict);
-       printf("%lu\tDirty buffers written by trickle-sync thread.\n",
+       dl("Dirty buffers written by trickle-sync thread.\n",
            (u_long)gsp->st_page_trickle);
-       printf("%lu\tCurrent clean buffer count.\n",
+       dl("Current clean buffer count.\n",
            (u_long)gsp->st_page_clean);
-       printf("%lu\tCurrent dirty buffer count.\n",
+       dl("Current dirty buffer count.\n",
            (u_long)gsp->st_page_dirty);
-       printf("%lu\tNumber of hash buckets used for page location.\n",
+       dl("Number of hash buckets used for page location.\n",
            (u_long)gsp->st_hash_buckets);
-       printf("%lu\tTotal number of times hash chains searched for a page.\n",
+       dl("Total number of times hash chains searched for a page.\n",
            (u_long)gsp->st_hash_searches);
-       printf("%lu\tThe longest hash chain searched for a page.\n",
+       dl("The longest hash chain searched for a page.\n",
            (u_long)gsp->st_hash_longest);
-       printf(
-           "%lu\tTotal number of hash buckets examined for page location.\n",
+       dl("Total number of hash buckets examined for page location.\n",
            (u_long)gsp->st_hash_examined);
-       printf("%lu\tThe number of region locks granted without waiting.\n",
+       dl("The number of region locks granted without waiting.\n",
            (u_long)gsp->st_region_nowait);
-       printf("%lu\tThe number of region locks granted after waiting.\n",
+       dl("The number of region locks granted after waiting.\n",
            (u_long)gsp->st_region_wait);
 
        for (; fsp != NULL && *fsp != NULL; ++fsp) {
                printf("%s\n", DB_LINE);
                printf("%s\n", (*fsp)->file_name);
-               printf("%lu\tPage size.\n", (u_long)(*fsp)->st_pagesize);
-               printf("%lu\tRequested pages found in the cache",
+               dl("Page size.\n", (u_long)(*fsp)->st_pagesize);
+               dl("Requested pages found in the cache",
                    (u_long)(*fsp)->st_cache_hit);
                if ((*fsp)->st_cache_hit + (*fsp)->st_cache_miss != 0)
                        printf(" (%.0f%%)", ((double)(*fsp)->st_cache_hit /
                            ((*fsp)->st_cache_hit + (*fsp)->st_cache_miss)) *
                            100);
                printf(".\n");
-       printf("%lu\tRequested pages mapped into the process' address space.\n",
+               dl("Requested pages mapped into the process' address space.\n",
                    (u_long)(*fsp)->st_map);
-               printf("%lu\tRequested pages not found in the cache.\n",
+               dl("Requested pages not found in the cache.\n",
                    (u_long)(*fsp)->st_cache_miss);
-               printf("%lu\tPages created in the cache.\n",
+               dl("Pages created in the cache.\n",
                    (u_long)(*fsp)->st_page_create);
-               printf("%lu\tPages read into the cache.\n",
+               dl("Pages read into the cache.\n",
                    (u_long)(*fsp)->st_page_in);
-       printf("%lu\tPages written from the cache to the backing file.\n",
+               dl("Pages written from the cache to the backing file.\n",
                    (u_long)(*fsp)->st_page_out);
        }
 }
@@ -358,46 +424,48 @@ void
 txn_stats(dbenv)
        DB_ENV *dbenv;
 {
-       DB_TXN_STAT *tstat;
+       DB_TXN_STAT *sp;
        u_int32_t i;
        const char *p;
 
-       if (txn_stat(dbenv->tx_info, &tstat, NULL))
+       if (txn_stat(dbenv->tx_info, &sp, NULL))
                err(1, NULL);
 
-       p = tstat->st_last_ckp.file == 0 ?
+       dl("Txn region reference count.\n", (u_long)sp->st_refcnt);
+       dl("Txn region size.\n", (u_long)sp->st_regsize);
+       p = sp->st_last_ckp.file == 0 ?
            "No checkpoint LSN." : "File/offset for last checkpoint LSN.";
-       printf("%lu/%lu\t%s\n", (u_long)tstat->st_last_ckp.file,
-           (u_long)tstat->st_last_ckp.offset, p);
-       p = tstat->st_pending_ckp.file == 0 ?
+       printf("%lu/%lu\t%s\n",
+           (u_long)sp->st_last_ckp.file, (u_long)sp->st_last_ckp.offset, p);
+       p = sp->st_pending_ckp.file == 0 ?
            "No pending checkpoint LSN." :
            "File/offset for last pending checkpoint LSN.";
        printf("%lu/%lu\t%s\n",
-           (u_long)tstat->st_pending_ckp.file,
-           (u_long)tstat->st_pending_ckp.offset, p);
-       if (tstat->st_time_ckp == 0)
+           (u_long)sp->st_pending_ckp.file,
+           (u_long)sp->st_pending_ckp.offset, p);
+       if (sp->st_time_ckp == 0)
                printf("0\tNo checkpoint timestamp.\n");
        else
                printf("%.24s\tCheckpoint timestamp.\n",
-                   ctime(&tstat->st_time_ckp));
+                   ctime(&sp->st_time_ckp));
        printf("%lx\tLast transaction ID allocated.\n",
-           (u_long)tstat->st_last_txnid);
-       printf("%lu\tMaximum number of active transactions.\n",
-           (u_long)tstat->st_maxtxns);
-       printf("%lu\tNumber of transactions begun.\n",
-           (u_long)tstat->st_nbegins);
-       printf("%lu\tNumber of transactions aborted.\n",
-           (u_long)tstat->st_naborts);
-       printf("%lu\tNumber of transactions committed.\n",
-           (u_long)tstat->st_ncommits);
-       printf("%lu\tActive transactions.\n", (u_long)tstat->st_nactive);
-       qsort(tstat->st_txnarray,
-           tstat->st_nactive, sizeof(tstat->st_txnarray[0]), txn_compare);
-       for (i = 0; i < tstat->st_nactive; ++i)
+           (u_long)sp->st_last_txnid);
+       dl("Maximum number of active transactions.\n", (u_long)sp->st_maxtxns);
+       dl("Number of transactions begun.\n", (u_long)sp->st_nbegins);
+       dl("Number of transactions aborted.\n", (u_long)sp->st_naborts);
+       dl("Number of transactions committed.\n", (u_long)sp->st_ncommits);
+       dl("The number of region locks granted without waiting.\n",
+           (u_long)sp->st_region_nowait);
+       dl("The number of region locks granted after waiting.\n",
+           (u_long)sp->st_region_wait);
+       dl("Active transactions.\n", (u_long)sp->st_nactive);
+       qsort(sp->st_txnarray,
+           sp->st_nactive, sizeof(sp->st_txnarray[0]), txn_compare);
+       for (i = 0; i < sp->st_nactive; ++i)
                printf("\tid: %lx; initial LSN file/offest %lu/%lu\n",
-                   (u_long)tstat->st_txnarray[i].txnid,
-                   (u_long)tstat->st_txnarray[i].lsn.file,
-                   (u_long)tstat->st_txnarray[i].lsn.offset);
+                   (u_long)sp->st_txnarray[i].txnid,
+                   (u_long)sp->st_txnarray[i].lsn.file,
+                   (u_long)sp->st_txnarray[i].lsn.offset);
 }
 
 int
@@ -417,25 +485,41 @@ txn_compare(a1, b1)
 }
 
 /*
+ * dl --
+ *     Display a big value.
+ */
+void
+dl(msg, value)
+       const char *msg;
+       u_long value;
+{
+       /*
+        * Two formats: if less than 10 million, display as the number, if
+        * greater than 10 million display as ###M.
+        */
+       if (value < 10000000)
+               printf("%lu\t%s", value, msg);
+       else
+               printf("%luM\t%s", value / 1000000, msg);
+}
+
+/*
  * prflags --
  *     Print out flag values.
  */
 void
-prflags(flags, fn)
+prflags(flags, fnp)
        u_int32_t flags;
-       FN const *fn;
-{
        const FN *fnp;
-       int found;
+{
        const char *sep;
 
        sep = " ";
        printf("Flags:");
-       for (found = 0, fnp = fn; fnp->mask != 0; ++fnp)
+       for (; fnp->mask != 0; ++fnp)
                if (fnp->mask & flags) {
                        printf("%s%s", sep, fnp->name);
                        sep = ", ";
-                       found = 1;
                }
        printf("\n");
 }
@@ -450,7 +534,7 @@ db_init(home, ttype)
        test_t ttype;
 {
        DB_ENV *dbenv;
-       int flags;
+       u_int32_t flags;
 
        if ((dbenv = (DB_ENV *)malloc(sizeof(DB_ENV))) == NULL) {
                errno = ENOMEM;
@@ -467,13 +551,16 @@ db_init(home, ttype)
        switch (ttype) {
        case T_DB:
        case T_MPOOL:
-               flags |= DB_INIT_MPOOL;
+               LF_SET(DB_INIT_MPOOL);
+               break;
+       case T_LOCK:
+               LF_SET(DB_INIT_LOCK);
                break;
        case T_LOG:
-               flags |= DB_INIT_LOG;
+               LF_SET(DB_INIT_LOG);
                break;
        case T_TXN:
-               flags |= DB_INIT_TXN;
+               LF_SET(DB_INIT_TXN);
                break;
        case T_NOTSET:
                abort();
@@ -493,7 +580,7 @@ db_init(home, ttype)
 
        /* Turn off the DB_INIT_MPOOL flag if it's a database. */
        if (ttype == T_DB)
-               flags &= ~DB_INIT_MPOOL;
+               LF_CLR(DB_INIT_MPOOL);
 
        /* Set the error output options -- this time we want a message. */
        memset(dbenv, 0, sizeof(*dbenv));
@@ -508,6 +595,21 @@ db_init(home, ttype)
 }
 
 /*
+ * argcheck --
+ *     Return if argument flags are okay.
+ */
+int
+argcheck(arg, ok_args)
+       char *arg;
+       const char *ok_args;
+{
+       for (; *arg != '\0'; ++arg)
+               if (strchr(ok_args, *arg) == NULL)
+                       return (0);
+       return (1);
+}
+
+/*
  * oninit --
  *     Interrupt signal handler.
  */
@@ -523,6 +625,7 @@ onint(signo)
 void
 usage()
 {
-       fprintf(stderr, "usage: db_stat [-mlt] [-d file] [-h home]\n");
+       fprintf(stderr,
+    "usage: db_stat [-clmNt] [-C Acflmo] [-d file] [-h home] [-M Ahlm]\n");
        exit (1);
 }
index 2a2e3da..4f3ffd8 100644 (file)
@@ -1,7 +1,7 @@
 /*-
  * See the file LICENSE for redistribution information.
  *
- * Copyright (c) 1996, 1997
+ * Copyright (c) 1996, 1997, 1998
  *     Sleepycat Software.  All rights reserved.
  */
 /*
 #include "config.h"
 
 #ifndef lint
-static const char sccsid[] = "@(#)txn.c        10.39 (Sleepycat) 1/8/98";
+static const char sccsid[] = "@(#)txn.c        10.58 (Sleepycat) 5/31/98";
 #endif /* not lint */
 
 
 #ifndef NO_SYSTEM_INCLUDES
 #include <sys/types.h>
-#include <sys/mman.h>
-#include <sys/stat.h>
 
 #include <errno.h>
-#include <fcntl.h>
-#include <stddef.h>
-#include <stdio.h>
-#include <stdlib.h>
 #include <string.h>
 #include <time.h>
-#include <unistd.h>
 #endif
 
-#include "shqueue.h"
 #include "db_int.h"
+#include "shqueue.h"
 #include "db_page.h"
 #include "db_shash.h"
 #include "txn.h"
@@ -74,9 +67,9 @@ static const char sccsid[] = "@(#)txn.c       10.39 (Sleepycat) 1/8/98";
 #include "common_ext.h"
 
 static int __txn_check_running __P((const DB_TXN *));
-static int __txn_create __P((DB_ENV *, const char *, u_int));
 static int __txn_end __P((DB_TXN *, int));
 static int __txn_grow_region __P((DB_TXNMGR *));
+static int __txn_init __P((DB_TXNREGION *));
 static int __txn_undo __P((DB_TXN *));
 static int __txn_validate_region __P((DB_TXNMGR *));
 
@@ -85,30 +78,20 @@ static int __txn_validate_region __P((DB_TXNMGR *));
  * It assumes that a lock manager and log manager that conform to the db_log(3)
  * and db_lock(3) interfaces exist.
  *
- * Create and initialize a transaction region in shared memory.
+ * Initialize a transaction region in shared memory.
  * Return 0 on success, errno on failure.
  */
 static int
-__txn_create(dbenv, path, mode)
-       DB_ENV *dbenv;
-       const char *path;
-       u_int mode;
-{
+__txn_init(txn_region)
        DB_TXNREGION *txn_region;
+{
        time_t now;
-       int fd, maxtxns, ret;
 
-       maxtxns = dbenv->tx_max != 0 ? dbenv->tx_max : 1000;
        (void)time(&now);
 
-       /* Region may have existed.  If it didn't, the open will fail. */
-       if ((ret = __db_rcreate(dbenv, DB_APP_NONE, path, DEFAULT_TXN_FILE,
-           mode, TXN_REGION_SIZE(maxtxns), 0, &fd, &txn_region)) != 0)
-               return (ret);
-
+       /* maxtxns is already initialized. */
        txn_region->magic = DB_TXNMAGIC;
        txn_region->version = DB_TXNVERSION;
-       txn_region->maxtxns = maxtxns;
        txn_region->last_txnid = TXN_MINIMUM;
        /* XXX If we ever do more types of locking and logging, this changes. */
        txn_region->logtype = 0;
@@ -118,33 +101,22 @@ __txn_create(dbenv, path, mode)
        ZERO_LSN(txn_region->pending_ckp);
        SH_TAILQ_INIT(&txn_region->active_txn);
        __db_shalloc_init((void *)&txn_region[1],
-           TXN_REGION_SIZE(maxtxns) - sizeof(DB_TXNREGION));
-
-       /* Unlock the region. */
-       (void)__db_mutex_unlock(&txn_region->hdr.lock, fd);
+           TXN_REGION_SIZE(txn_region->maxtxns) - sizeof(DB_TXNREGION));
 
-       /* Now unmap and close the region. */
-       if ((ret = __db_rclose(dbenv, fd, txn_region)) != 0) {
-               (void)txn_unlink(path, 1 /* force */, dbenv);
-               return (ret);
-       }
        return (0);
 }
 
 int
 txn_open(path, flags, mode, dbenv, mgrpp)
        const char *path;
-       int flags, mode;
+       u_int32_t flags;
+       int mode;
        DB_ENV *dbenv;
        DB_TXNMGR **mgrpp;
 {
        DB_TXNMGR *tmgrp;
-       DB_TXNREGION *txn_regionp;
-       int fd, ret, retry_cnt;
-
-       tmgrp = NULL;
-       txn_regionp = NULL;
-       fd = -1;
+       u_int32_t maxtxns;
+       int ret;
 
        /* Validate arguments. */
        if (dbenv == NULL)
@@ -157,52 +129,57 @@ txn_open(path, flags, mode, dbenv, mgrpp)
        if ((ret = __db_fchk(dbenv, "txn_open", flags, OKFLAGS)) != 0)
                return (ret);
 
-       retry_cnt = 0;
-retry: if (LF_ISSET(DB_CREATE) && (ret = __txn_create(dbenv, path, mode)) != 0)
-               if (ret == EAGAIN && ++retry_cnt < 0) {
-                       (void)__db_sleep(1, 0);
-                       goto retry;
-               } else  /* We did not really create the region */
-                       flags &= ~DB_CREATE;
-
-       retry_cnt = 0;
-retry1:        if ((ret = __db_ropen(dbenv, DB_APP_NONE, path, DEFAULT_TXN_FILE,
-           flags & ~(DB_CREATE | DB_THREAD | DB_TXN_NOSYNC),
-           &fd, &txn_regionp)) != 0) {
-               if (ret == EAGAIN && ++retry_cnt < 3) {
-                       (void)__db_sleep(1, 0);
-                       goto retry1;
-               }
-               goto out;
-       }
-
-
-       /* Check if valid region. */
-       if (txn_regionp->magic != DB_TXNMAGIC) {
-               __db_err(dbenv, "txn_open: Bad magic number");
-               ret = EINVAL;
-               goto out;
-       }
+       maxtxns = dbenv->tx_max != 0 ? dbenv->tx_max : 20;
 
        /* Now, create the transaction manager structure and set its fields. */
-       if ((tmgrp = (DB_TXNMGR *)__db_malloc(sizeof(DB_TXNMGR))) == NULL) {
+       if ((tmgrp = (DB_TXNMGR *)__db_calloc(1, sizeof(DB_TXNMGR))) == NULL) {
                __db_err(dbenv, "txn_open: %s", strerror(ENOMEM));
-               ret = ENOMEM;
-               goto out;
+               return (ENOMEM);
        }
 
+       /* Initialize the transaction manager structure. */
+       tmgrp->mutexp = NULL;
        tmgrp->dbenv = dbenv;
        tmgrp->recover =
            dbenv->tx_recover == NULL ? __db_dispatch : dbenv->tx_recover;
-       tmgrp->region = txn_regionp;
-       tmgrp->reg_size = txn_regionp->hdr.size;
-       tmgrp->fd = fd;
        tmgrp->flags = LF_ISSET(DB_TXN_NOSYNC | DB_THREAD);
-       tmgrp->mem = &txn_regionp[1];
-       tmgrp->mutexp = NULL;
        TAILQ_INIT(&tmgrp->txn_chain);
+
+       /* Join/create the txn region. */
+       tmgrp->reginfo.dbenv = dbenv;
+       tmgrp->reginfo.appname = DB_APP_NONE;
+       if (path == NULL)
+               tmgrp->reginfo.path = NULL;
+       else
+               if ((tmgrp->reginfo.path = (char *)__db_strdup(path)) == NULL)
+                       goto err;
+       tmgrp->reginfo.file = DEFAULT_TXN_FILE;
+       tmgrp->reginfo.mode = mode;
+       tmgrp->reginfo.size = TXN_REGION_SIZE(maxtxns);
+       tmgrp->reginfo.dbflags = flags;
+       tmgrp->reginfo.addr = NULL;
+       tmgrp->reginfo.fd = -1;
+       tmgrp->reginfo.flags = dbenv->tx_max == 0 ? REGION_SIZEDEF : 0;
+       if ((ret = __db_rattach(&tmgrp->reginfo)) != 0)
+               goto err;
+
+       /* Fill in region-related fields. */
+       tmgrp->region = tmgrp->reginfo.addr;
+       tmgrp->mem = &tmgrp->region[1];
+
+       if (F_ISSET(&tmgrp->reginfo, REGION_CREATED)) {
+               tmgrp->region->maxtxns = maxtxns;
+               if ((ret = __txn_init(tmgrp->region)) != 0)
+                       goto err;
+
+       } else if (tmgrp->region->magic != DB_TXNMAGIC) {
+               /* Check if valid region. */
+               __db_err(dbenv, "txn_open: Bad magic number");
+               ret = EINVAL;
+               goto err;
+       }
+
        if (LF_ISSET(DB_THREAD)) {
-               LOCK_TXNREGION(tmgrp);
                if ((ret = __db_shalloc(tmgrp->mem, sizeof(db_mutex_t),
                    MUTEX_ALIGNMENT, &tmgrp->mutexp)) == 0)
                        /*
@@ -211,25 +188,27 @@ retry1:   if ((ret = __db_ropen(dbenv, DB_APP_NONE, path, DEFAULT_TXN_FILE,
                         * to be ignored.  We put 0 here as a valid placeholder.
                         */
                        __db_mutex_init(tmgrp->mutexp, 0);
-               UNLOCK_TXNREGION(tmgrp);
                if (ret != 0)
-                       goto out;
+                       goto err;
        }
+
+       UNLOCK_TXNREGION(tmgrp);
        *mgrpp = tmgrp;
        return (0);
 
-out:   if (txn_regionp != NULL)
-               (void)__db_rclose(dbenv, fd, txn_regionp);
-       if (flags & DB_CREATE)
-               (void)txn_unlink(path, 1, dbenv);
-       if (tmgrp != NULL) {
-               if (tmgrp->mutexp != NULL) {
-                       LOCK_TXNREGION(tmgrp);
+err:   if (tmgrp->reginfo.addr != NULL) {
+               if (tmgrp->mutexp != NULL)
                        __db_shalloc_free(tmgrp->mem, tmgrp->mutexp);
-                       UNLOCK_TXNREGION(tmgrp);
-               }
-               __db_free(tmgrp);
+
+               UNLOCK_TXNREGION(tmgrp);
+               (void)__db_rdetach(&tmgrp->reginfo);
+               if (F_ISSET(&tmgrp->reginfo, REGION_CREATED))
+                       (void)txn_unlink(path, 1, dbenv);
        }
+
+       if (tmgrp->reginfo.path != NULL)
+               FREES(tmgrp->reginfo.path);
+       FREE(tmgrp, sizeof(*tmgrp));
        return (ret);
 }
 
@@ -244,77 +223,83 @@ txn_begin(tmgrp, parent, txnpp)
        DB_TXN *parent;
        DB_TXN **txnpp;
 {
-       TXN_DETAIL *txnp;
+       DB_LSN begin_lsn;
        DB_TXN *retp;
-       int id, ret;
+       TXN_DETAIL *txnp;
+       size_t off;
+       u_int32_t id;
+       int ret;
+
+       txnp = NULL;
+       *txnpp = NULL;
+
+       if ((retp = (DB_TXN *)__db_malloc(sizeof(DB_TXN))) == NULL) {
+               __db_err(tmgrp->dbenv, "txn_begin : %s", strerror(ENOMEM));
+               return (ENOMEM);
+       }
+
+       /*
+        * We do not have to write begin records (and if we do not, then we
+        * need never write records for read-only transactions).  However,
+        * we do need to find the current LSN so that we can store it in the
+        * transaction structure, so we can know where to take checkpoints.
+        */
+       if (tmgrp->dbenv->lg_info != NULL && (ret =
+           log_put(tmgrp->dbenv->lg_info, &begin_lsn, NULL, DB_CURLSN)) != 0)
+               goto err2;
 
        LOCK_TXNREGION(tmgrp);
 
+       /* Make sure that last_txnid is not going to wrap around. */
+       if (tmgrp->region->last_txnid == TXN_INVALID) {
+               __db_err(tmgrp->dbenv, "txn_begin: %s  %s",
+                   "Transaction ID wrapping.",
+                   "Snapshot your database and start a new log.");
+               ret = EINVAL;
+               goto err1;
+       }
+
        if ((ret = __txn_validate_region(tmgrp)) != 0)
-               goto err;
+               goto err1;
 
        /* Allocate a new transaction detail structure. */
        if ((ret = __db_shalloc(tmgrp->mem, sizeof(TXN_DETAIL), 0, &txnp)) != 0
            && ret == ENOMEM && (ret = __txn_grow_region(tmgrp)) == 0)
                ret = __db_shalloc(tmgrp->mem, sizeof(TXN_DETAIL), 0, &txnp);
-
        if (ret != 0)
-               goto err;
-
-       /* Make sure that last_txnid is not going to wrap around. */
-       if (tmgrp->region->last_txnid == TXN_INVALID)
-               return (EINVAL);
-
-       if ((retp = (DB_TXN *)__db_malloc(sizeof(DB_TXN))) == NULL) {
-               __db_err(tmgrp->dbenv, "txn_begin : %s", strerror(ENOMEM));
-               ret = ENOMEM;
                goto err1;
-       }
+
+       /* Place transaction on active transaction list. */
+       SH_TAILQ_INSERT_HEAD(&tmgrp->region->active_txn,
+           txnp, links, __txn_detail);
 
        id = ++tmgrp->region->last_txnid;
        tmgrp->region->nbegins++;
 
        txnp->txnid = id;
+       txnp->begin_lsn = begin_lsn;
        ZERO_LSN(txnp->last_lsn);
-       ZERO_LSN(txnp->begin_lsn);
        txnp->last_lock = 0;
        txnp->status = TXN_RUNNING;
-       SH_TAILQ_INSERT_HEAD(&tmgrp->region->active_txn,
-           txnp, links, __txn_detail);
-
+       off = (u_int8_t *)txnp - (u_int8_t *)tmgrp->region;
        UNLOCK_TXNREGION(tmgrp);
 
        ZERO_LSN(retp->last_lsn);
        retp->txnid = id;
        retp->parent = parent;
-       retp->off = (u_int8_t *)txnp - (u_int8_t *)tmgrp->region;
        retp->mgrp = tmgrp;
-
-       if (tmgrp->dbenv->lg_info != NULL &&
-           (ret = __txn_regop_log(tmgrp->dbenv->lg_info,
-               retp, &txnp->begin_lsn, 0, TXN_BEGIN)) != 0) {
-
-               /* Deallocate transaction. */
-               LOCK_TXNREGION(tmgrp);
-               SH_TAILQ_REMOVE(&tmgrp->region->active_txn,
-                   txnp, links, __txn_detail);
-               __db_shalloc_free(tmgrp->mem, txnp);
-               UNLOCK_TXNREGION(tmgrp);
-               __db_free(retp);
-               return (ret);
-       }
+       retp->off = off;
 
        LOCK_TXNTHREAD(tmgrp);
        TAILQ_INSERT_TAIL(&tmgrp->txn_chain, retp, links);
        UNLOCK_TXNTHREAD(tmgrp);
 
-       *txnpp  = retp;
+       *txnpp = retp;
        return (0);
 
-err1:
-       __db_shalloc_free(tmgrp->mem, txnp);
-err:
-       UNLOCK_TXNREGION(tmgrp);
+err1:  UNLOCK_TXNREGION(tmgrp);
+
+err2:  __db_free(retp);
        return (ret);
 }
 
@@ -332,12 +317,15 @@ txn_commit(txnp)
        if ((ret = __txn_check_running(txnp)) != 0)
                return (ret);
 
-       /* Sync the log. */
+       /*
+        * If there are any log records, write a log record and sync
+        * the log, else do no log writes.
+        */
        if ((logp = txnp->mgrp->dbenv->lg_info) != NULL &&
-           (ret = __txn_regop_log(logp,
-           txnp, &txnp->last_lsn,
-           F_ISSET(txnp->mgrp, DB_TXN_NOSYNC) ? 0 : DB_FLUSH, TXN_COMMIT))
-           != 0)
+           !IS_ZERO_LSN(txnp->last_lsn) &&
+           (ret = __txn_regop_log(logp, txnp, &txnp->last_lsn,
+           F_ISSET(txnp->mgrp, DB_TXN_NOSYNC) ? 0 : DB_FLUSH,
+           TXN_COMMIT)) != 0)
                return (ret);
 
        return (__txn_end(txnp, 1));
@@ -371,8 +359,8 @@ int
 txn_prepare(txnp)
        DB_TXN *txnp;
 {
-       int ret;
        TXN_DETAIL *tp;
+       int ret;
 
        if ((ret = __txn_check_running(txnp)) != 0)
                return (ret);
@@ -414,21 +402,23 @@ txn_close(tmgrp)
        DB_TXN *txnp;
        int ret, t_ret;
 
+       ret = 0;
+
        /*
         * This function had better only be called once per process
         * (i.e., not per thread), so there should be no synchronization
         * required.
         */
-       for (ret = 0, txnp = TAILQ_FIRST(&tmgrp->txn_chain);
-           txnp != TAILQ_END(&tmgrp->txn_chain);
-           txnp = TAILQ_FIRST(&tmgrp->txn_chain)) {
-               if ((t_ret = txn_abort(txnp)) != 0 && ret == 0)
-                       ret = t_ret;
-       }
+       while ((txnp =
+           TAILQ_FIRST(&tmgrp->txn_chain)) != TAILQ_END(&tmgrp->txn_chain))
+               if ((t_ret = txn_abort(txnp)) != 0) {
+                       __txn_end(txnp, 0);
+                       if (ret == 0)
+                               ret = t_ret;
+               }
 
-       if (tmgrp->dbenv->lg_info && (t_ret =
-           log_flush(tmgrp->dbenv->lg_info, NULL)) != 0 &&
-           ret == 0)
+       if (tmgrp->dbenv->lg_info &&
+           (t_ret = log_flush(tmgrp->dbenv->lg_info, NULL)) != 0 && ret == 0)
                ret = t_ret;
 
        if (tmgrp->mutexp != NULL) {
@@ -437,12 +427,12 @@ txn_close(tmgrp)
                UNLOCK_TXNREGION(tmgrp);
        }
 
-       if ((t_ret = __db_rclose(tmgrp->dbenv, tmgrp->fd, tmgrp->region)) != 0
-           && ret == 0)
+       if ((t_ret = __db_rdetach(&tmgrp->reginfo)) != 0 && ret == 0)
                ret = t_ret;
 
-       if (ret == 0)
-               __db_free(tmgrp);
+       if (tmgrp->reginfo.path != NULL)
+               FREES(tmgrp->reginfo.path);
+       FREE(tmgrp, sizeof(*tmgrp));
 
        return (ret);
 }
@@ -457,8 +447,19 @@ txn_unlink(path, force, dbenv)
        int force;
        DB_ENV *dbenv;
 {
-       return (__db_runlink(dbenv,
-           DB_APP_NONE, path, DEFAULT_TXN_FILE, force));
+       REGINFO reginfo;
+       int ret;
+
+       memset(&reginfo, 0, sizeof(reginfo));
+       reginfo.dbenv = dbenv;
+       reginfo.appname = DB_APP_NONE;
+       if (path != NULL && (reginfo.path = (char *)__db_strdup(path)) == NULL)
+               return (ENOMEM);
+       reginfo.file = DEFAULT_TXN_FILE;
+       ret = __db_runlink(&reginfo, force);
+       if (reginfo.path != NULL)
+               FREES(reginfo.path);
+       return (ret);
 }
 
 /* Internal routines. */
@@ -540,10 +541,10 @@ static int
 __txn_undo(txnp)
        DB_TXN *txnp;
 {
-       DB_TXNMGR *mgr;
-       DB_LOG *logp;
        DBT rdbt;
+       DB_LOG *logp;
        DB_LSN key_lsn;
+       DB_TXNMGR *mgr;
        int ret;
 
        mgr = txnp->mgrp;
@@ -594,7 +595,7 @@ __txn_undo(txnp)
 int
 txn_checkpoint(mgr, kbytes, minutes)
        const DB_TXNMGR *mgr;
-       int kbytes, minutes;
+       u_int32_t kbytes, minutes;
 {
        TXN_DETAIL *txnp;
        DB_LSN ckp_lsn, last_ckp;
@@ -603,10 +604,6 @@ txn_checkpoint(mgr, kbytes, minutes)
        time_t last_ckp_time, now;
        int ret;
 
-       /* Check usage. */
-       if (kbytes < 0 || minutes < 0)
-               return (EINVAL);
-
        /*
         * Check if we need to run recovery.
         */
@@ -678,8 +675,8 @@ do_ckp:
        if (mgr->dbenv->mp_info != NULL &&
            (ret = memp_sync(mgr->dbenv->mp_info, &ckp_lsn)) != 0) {
                /*
-                * ret < 0 means that there are still buffers to flush;
-                * the checkpoint is not complete. Back off and try again.
+                * ret == DB_INCOMPLETE means that there are still buffers to
+                * flush, the checkpoint is not complete.  Wait and try again.
                 */
                if (ret > 0)
                        __db_err(mgr->dbenv,
@@ -711,9 +708,9 @@ do_ckp:
 }
 
 /*
- * This is called at every interface to verify if the region
- * has changed size, and if so, to remap the region in and
- * reset the process pointers.
+ * __txn_validate_region --
+ *     Called at every interface to verify if the region has changed size,
+ *     and if so, to remap the region in and reset the process' pointers.
  */
 static int
 __txn_validate_region(tp)
@@ -721,15 +718,15 @@ __txn_validate_region(tp)
 {
        int ret;
 
-       if (tp->reg_size == tp->region->hdr.size)
+       if (tp->reginfo.size == tp->region->hdr.size)
                return (0);
 
-       /* Grow the region. */
-       if ((ret = __db_rremap(tp->dbenv, tp->region,
-           tp->reg_size, tp->region->hdr.size, tp->fd, &tp->region)) != 0)
+       /* Detach/reattach the region. */
+       if ((ret = __db_rreattach(&tp->reginfo, tp->region->hdr.size)) != 0)
                return (ret);
 
-       tp->reg_size = tp->region->hdr.size;
+       /* Reset region information. */
+       tp->region = tp->reginfo.addr;
        tp->mem = &tp->region[1];
 
        return (0);
@@ -739,27 +736,26 @@ static int
 __txn_grow_region(tp)
        DB_TXNMGR *tp;
 {
-       size_t incr;
+       size_t incr, oldsize;
        u_int32_t mutex_offset, oldmax;
        u_int8_t *curaddr;
        int ret;
 
        oldmax = tp->region->maxtxns;
        incr = oldmax * sizeof(DB_TXN);
-       mutex_offset = (u_int8_t *)tp->mutexp - (u_int8_t *)tp->region;
+       mutex_offset = tp->mutexp != NULL ?
+           (u_int8_t *)tp->mutexp - (u_int8_t *)tp->region : 0;
 
-       if ((ret = __db_rgrow(tp->dbenv, tp->fd, incr)) != 0)
-               return (ret);
-
-       if ((ret = __db_rremap(tp->dbenv, tp->region,
-           tp->reg_size, tp->reg_size + incr, tp->fd, &tp->region)) != 0)
+       oldsize = tp->reginfo.size;
+       if ((ret = __db_rgrow(&tp->reginfo, oldsize + incr)) != 0)
                return (ret);
+       tp->region = tp->reginfo.addr;
 
        /* Throw the new space on the free list. */
-       curaddr = (u_int8_t *)tp->region + tp->reg_size;
+       curaddr = (u_int8_t *)tp->region + oldsize;
        tp->mem = &tp->region[1];
-       tp->reg_size += incr;
-       tp->mutexp = (db_mutex_t *)((u_int8_t *)tp->region + mutex_offset);
+       tp->mutexp = mutex_offset != 0 ?
+           (db_mutex_t *)((u_int8_t *)tp->region + mutex_offset) : NULL;
 
        *((size_t *)curaddr) = incr - sizeof(size_t);
        curaddr += sizeof(size_t);
@@ -826,6 +822,11 @@ txn_stat(mgr, statp, db_malloc)
                        break;
        }
 
+       stats->st_region_wait = mgr->region->hdr.lock.mutex_set_wait;
+       stats->st_region_nowait = mgr->region->hdr.lock.mutex_set_nowait;
+       stats->st_refcnt = mgr->region->hdr.refcnt;
+       stats->st_regsize = mgr->region->hdr.size;
+
        UNLOCK_TXNREGION(mgr);
        *statp = stats;
        return (0);
index 40bb63e..04809b6 100644 (file)
@@ -1,14 +1,12 @@
 /*-
  * See the file LICENSE for redistribution information.
  *
- * Copyright (c) 1996, 1997
+ * Copyright (c) 1996, 1997, 1998
  *     Sleepycat Software.  All rights reserved.
  *
- *     @(#)txn.src     10.1 (Sleepycat) 4/12/97
- *
- * This is the source file used to create the logging functions for the
- * transaction system.
+ *     @(#)txn.src     10.3 (Sleepycat) 4/10/98
  */
+
 PREFIX txn
 
 /*
index 3862746..f03a529 100644 (file)
@@ -15,8 +15,6 @@
 #include "db_dispatch.h"
 #include "txn.h"
 #include "db_am.h"
-#include "common_ext.h"
-
 /*
  * PUBLIC: int __txn_regop_log
  * PUBLIC:     __P((DB_LOG *, DB_TXN *, DB_LSN *, u_int32_t,
@@ -58,7 +56,7 @@ int __txn_regop_log(logp, txnid, ret_lsnp, flags,
        bp += sizeof(DB_LSN);
        memcpy(bp, &opcode, sizeof(opcode));
        bp += sizeof(opcode);
-#ifdef DEBUG
+#ifdef DIAGNOSTIC
        if ((u_int32_t)(bp - (u_int8_t *)logrec.data) != logrec.size)
                fprintf(stderr, "Error in log record length");
 #endif
@@ -74,22 +72,23 @@ int __txn_regop_log(logp, txnid, ret_lsnp, flags,
  * PUBLIC:    __P((DB_LOG *, DBT *, DB_LSN *, int, void *));
  */
 int
-__txn_regop_print(notused1, dbtp, lsnp, notused3, notused4)
+__txn_regop_print(notused1, dbtp, lsnp, notused2, notused3)
        DB_LOG *notused1;
        DBT *dbtp;
        DB_LSN *lsnp;
-       int notused3;
-       void *notused4;
+       int notused2;
+       void *notused3;
 {
        __txn_regop_args *argp;
        u_int32_t i;
-       int c, ret;
+       u_int ch;
+       int ret;
 
        i = 0;
-       c = 0;
+       ch = 0;
        notused1 = NULL;
-       notused3 = 0;
-       notused4 = NULL;
+       notused2 = 0;
+       notused3 = NULL;
 
        if ((ret = __txn_regop_read(dbtp->data, &argp)) != 0)
                return (ret);
@@ -186,7 +185,7 @@ int __txn_ckp_log(logp, txnid, ret_lsnp, flags,
        else
                memset(bp, 0, sizeof(*last_ckp));
        bp += sizeof(*last_ckp);
-#ifdef DEBUG
+#ifdef DIAGNOSTIC
        if ((u_int32_t)(bp - (u_int8_t *)logrec.data) != logrec.size)
                fprintf(stderr, "Error in log record length");
 #endif
@@ -202,22 +201,23 @@ int __txn_ckp_log(logp, txnid, ret_lsnp, flags,
  * PUBLIC:    __P((DB_LOG *, DBT *, DB_LSN *, int, void *));
  */
 int
-__txn_ckp_print(notused1, dbtp, lsnp, notused3, notused4)
+__txn_ckp_print(notused1, dbtp, lsnp, notused2, notused3)
        DB_LOG *notused1;
        DBT *dbtp;
        DB_LSN *lsnp;
-       int notused3;
-       void *notused4;
+       int notused2;
+       void *notused3;
 {
        __txn_ckp_args *argp;
        u_int32_t i;
-       int c, ret;
+       u_int ch;
+       int ret;
 
        i = 0;
-       c = 0;
+       ch = 0;
        notused1 = NULL;
-       notused3 = 0;
-       notused4 = NULL;
+       notused2 = 0;
+       notused3 = NULL;
 
        if ((ret = __txn_ckp_read(dbtp->data, &argp)) != 0)
                return (ret);
index 679cffb..e53dc5f 100644 (file)
@@ -1,7 +1,7 @@
 /*-
  * See the file LICENSE for redistribution information.
  *
- * Copyright (c) 1996, 1997
+ * Copyright (c) 1996, 1997, 1998
  *     Sleepycat Software.  All rights reserved.
  */
 /*
 #include "config.h"
 
 #ifndef lint
-static const char sccsid[] = "@(#)txn_rec.c    10.6 (Sleepycat) 10/25/97";
+static const char sccsid[] = "@(#)txn_rec.c    10.11 (Sleepycat) 5/3/98";
 #endif /* not lint */
 
 #ifndef NO_SYSTEM_INCLUDES
 #include <sys/types.h>
 
-#include <stddef.h>
-#include <stdlib.h>
-#include <string.h>
+#include <errno.h>
 #endif
 
 #include "db_int.h"
 #include "db_page.h"
 #include "shqueue.h"
 #include "txn.h"
-#include "db_dispatch.h"
 #include "db_am.h"
-#include "common_ext.h"
 
 /*
  * PUBLIC: int __txn_regop_recover
@@ -69,7 +65,7 @@ __txn_regop_recover(logp, dbtp, lsnp, redo, info)
        DBT *dbtp;
        DB_LSN *lsnp;
        int redo;
-        void *info;
+       void *info;
 {
        __txn_regop_args *argp;
        int ret;
@@ -77,8 +73,8 @@ __txn_regop_recover(logp, dbtp, lsnp, redo, info)
 #ifdef DEBUG_RECOVER
        (void)__txn_regop_print(logp, dbtp, lsnp, redo, info);
 #endif
-       logp = logp;                    /* XXX: Shut the compiler up. */
-       redo = redo;
+       COMPQUIET(redo, 0);
+       COMPQUIET(logp, NULL);
 
        if ((ret = __txn_regop_read(dbtp->data, &argp)) != 0)
                return (ret);
@@ -90,10 +86,12 @@ __txn_regop_recover(logp, dbtp, lsnp, redo, info)
                        __db_txnlist_add(info, argp->txnid->txnid);
                break;
        case TXN_PREPARE:       /* Nothing to do. */
-       case TXN_BEGIN:
-               /* Call find so that we update the maxid. */
+               /* Call __db_txnlist_find so that we update the maxid. */
                (void)__db_txnlist_find(info, argp->txnid->txnid);
                break;
+       default:
+               ret = EINVAL;
+               break;
        }
 
        *lsnp = argp->prev_lsn;
@@ -118,13 +116,20 @@ __txn_ckp_recover(logp, dbtp, lsnp, redo, info)
 #ifdef DEBUG_RECOVER
        __txn_ckp_print(logp, dbtp, lsnp, redo, info);
 #endif
-       logp = logp;                    /* XXX: Shut the compiler up. */
-       redo = redo;
-       info = info;
+       COMPQUIET(logp, NULL);
 
        if ((ret = __txn_ckp_read(dbtp->data, &argp)) != 0)
                return (ret);
 
+       /*
+        * Check for 'restart' checkpoint record.  This occurs when the
+        * checkpoint lsn is equal to the lsn of the checkpoint record
+        * and means that we could set the transaction ID back to 1, so
+        * that we don't exhaust the transaction ID name space.
+        */
+       if (argp->ckp_lsn.file == lsnp->file &&
+           argp->ckp_lsn.offset == lsnp->offset)
+               __db_txnlist_gen(info, redo ? -1 : 1);
        *lsnp = argp->last_ckp;
        __db_free(argp);
        return (DB_TXN_CKP);
index 80f10d6..95f964f 100644 (file)
--- a/elf/elf.h
+++ b/elf/elf.h
@@ -168,6 +168,8 @@ typedef struct
 
 #define EM_PPC         20              /* PowerPC */
 
+#define EM_ARM         40              /* ARM */
+
 #define EM_SPARCV9     43              /* SPARC v9 64-bit */
 
 /* If it is necessary to assign new unofficial EM_* values, please
@@ -1086,6 +1088,24 @@ typedef Elf32_Addr Elf32_Conflict;
    that may still be in object files.  */
 #define R_PPC_TOC16            255
 
+
+/* ARM specific declarations */
+
+/* ARM relocs.  */
+
+#define R_ARM_NONE     0               /* No reloc */
+#define R_ARM_PC24     1               /* PC relative 26 bit branch */
+#define R_ARM_ABS32    2               /* Direct 32 bit  */
+#define R_ARM_REL32    3               /* PC relative 32 bit */
+#define R_ARM_COPY     20              /* Copy symbol at runtime */
+#define R_ARM_GLOB_DAT 21              /* Create GOT entry */
+#define R_ARM_JUMP_SLOT        22              /* Create PLT entry */
+#define R_ARM_RELATIVE 23              /* Adjust by program base */
+#define R_ARM_GOTOFF   24              /* 32 bit offset to GOT */
+#define R_ARM_GOTPC    25              /* 32 bit PC relative offset to GOT */
+#define R_ARM_GOT32    26              /* 32 bit GOT entry */
+#define R_ARM_PLT32    27              /* 32 bit PLT address */
+
 __END_DECLS
 
 #endif /* elf.h */
index 58f9da8..028467f 100644 (file)
@@ -93,8 +93,6 @@ const char *_dl_inhibit_rpath;                /* RPATH values which should be
    never be called.  */
 int _dl_starting_up;
 
-/* This variable contains the lowest stack address ever used.  */
-void *__libc_stack_end;
 
 static void dl_main (const ElfW(Phdr) *phdr,
                     ElfW(Half) phent,
index 73f502f..365b92e 100644 (file)
--- a/io/fts.c
+++ b/io/fts.c
@@ -1,5 +1,5 @@
 /*-
- * Copyright (c) 1990, 1993
+ * Copyright (c) 1990, 1993, 1994
  *     The Regents of the University of California.  All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -32,7 +32,7 @@
  */
 
 #if defined(LIBC_SCCS) && !defined(lint)
-static char sccsid[] = "@(#)fts.c      8.2 (Berkeley) 1/2/94";
+static char sccsid[] = "@(#)fts.c      8.6 (Berkeley) 8/14/94";
 #endif /* LIBC_SCCS and not lint */
 
 #include <sys/param.h>
@@ -65,7 +65,8 @@ static size_t  fts_maxarglen __P((char * const *)) internal_function;
 static void     fts_padjust __P((FTS *, void *)) internal_function;
 static int      fts_palloc __P((FTS *, size_t)) internal_function;
 static FTSENT  *fts_sort __P((FTS *, FTSENT *, int)) internal_function;
-static u_short  fts_stat __P((FTS *, FTSENT *, int)) internal_function;
+static u_short  fts_stat __P((FTS *, struct dirent *, FTSENT *, int))
+     internal_function;
 
 #ifndef MAX
 #define MAX(a, b)      ({ __typeof__ (a) _a = (a); \
@@ -142,7 +143,7 @@ fts_open(argv, options, compar)
                p->fts_level = FTS_ROOTLEVEL;
                p->fts_parent = parent;
                p->fts_accpath = p->fts_name;
-               p->fts_info = fts_stat(sp, p, ISSET(FTS_COMFOLLOW));
+               p->fts_info = fts_stat(sp, NULL, p, ISSET(FTS_COMFOLLOW));
 
                /* Command-line "." and ".." are real directories. */
                if (p->fts_info == FTS_DOT)
@@ -298,7 +299,7 @@ fts_read(sp)
 
        /* Any type of file may be re-visited; re-stat and re-turn. */
        if (instr == FTS_AGAIN) {
-               p->fts_info = fts_stat(sp, p, 0);
+               p->fts_info = fts_stat(sp, NULL, p, 0);
                return (p);
        }
 
@@ -310,7 +311,7 @@ fts_read(sp)
         */
        if (instr == FTS_FOLLOW &&
            (p->fts_info == FTS_SL || p->fts_info == FTS_SLNONE)) {
-               p->fts_info = fts_stat(sp, p, 1);
+               p->fts_info = fts_stat(sp, NULL, p, 1);
                if (p->fts_info == FTS_D && !ISSET(FTS_NOCHDIR))
                        if ((p->fts_symfd = open(".", O_RDONLY, 0)) < 0) {
                                p->fts_errno = errno;
@@ -398,7 +399,7 @@ next:       tmp = p;
                if (p->fts_instr == FTS_SKIP)
                        goto next;
                if (p->fts_instr == FTS_FOLLOW) {
-                       p->fts_info = fts_stat(sp, p, 1);
+                       p->fts_info = fts_stat(sp, NULL, p, 1);
                        if (p->fts_info == FTS_D && !ISSET(FTS_NOCHDIR))
                                if ((p->fts_symfd =
                                    open(".", O_RDONLY, 0)) < 0) {
@@ -577,7 +578,7 @@ fts_build(sp, type)
        FTSENT *cur, *tail;
        DIR *dirp;
        void *adjaddr;
-       int cderrno, descend, len, level, maxlen, nlinks, saved_errno;
+       int cderrno, descend, len, level, maxlen, nlinks, oflag, saved_errno;
        char *cp;
 
        /* Set current node pointer. */
@@ -587,7 +588,15 @@ fts_build(sp, type)
         * Open the directory for reading.  If this fails, we're done.
         * If being called from fts_read, set the fts_info field.
         */
-       if ((dirp = opendir(cur->fts_accpath)) == NULL) {
+#ifdef DTF_HIDEW
+       if (ISSET (FTS_WHITEOUT))
+               oflag = DTF_NODUP|DTF_REWIND;
+       else
+               oflag = DTF_HIDEW|DTF_NODUP|DTF_REWIND;
+#else
+# define __opendir2(path, flag) opendir(path)
+#endif
+       if ((dirp = __opendir2 (cur->fts_accpath, oflag)) == NULL) {
                if (type == BREAD) {
                        cur->fts_info = FTS_DNR;
                        cur->fts_errno = errno;
@@ -719,7 +728,7 @@ mem1:                               saved_errno = errno;
                        } else
                                p->fts_accpath = p->fts_name;
                        /* Stat it. */
-                       p->fts_info = fts_stat(sp, p, 0);
+                       p->fts_info = fts_stat(sp, dp, p, 0);
 
                        /* Decrement link count if applicable. */
                        if (nlinks > 0 && (p->fts_info == FTS_D ||
@@ -757,11 +766,15 @@ mem1:                             saved_errno = errno;
        }
 
        /*
-        * If descended after called from fts_children or called from
-        * fts_read and didn't find anything, get back.  If can't get
-        * back, done.
+        * If descended after called from fts_children or after called from
+        * fts_read and nothing found, get back.  At the root level we use
+        * the saved fd; if one of fts_open()'s arguments is a relative path
+        * to an empty directory, we wind up here with no other way back.  If
+        * can't get back, we're done.
         */
-       if (descend && (!nitems || type == BCHILD) && CHDIR(sp, "..")) {
+       if (descend && (type == BCHILD || !nitems) &&
+           (cur->fts_level == FTS_ROOTLEVEL ?
+            FCHDIR (sp, sp->fts_rfd) : CHDIR (sp, ".."))) {
                cur->fts_info = FTS_ERR;
                SET(FTS_STOP);
                return (NULL);
@@ -782,9 +795,10 @@ mem1:                              saved_errno = errno;
 
 static u_short
 internal_function
-fts_stat(sp, p, follow)
+fts_stat(sp, dp, p, follow)
        FTS *sp;
        register FTSENT *p;
+       struct dirent *dp;
        int follow;
 {
        register FTSENT *t;
@@ -796,6 +810,19 @@ fts_stat(sp, p, follow)
        /* If user needs stat info, stat buffer already allocated. */
        sbp = ISSET(FTS_NOSTAT) ? &sb : p->fts_statp;
 
+#ifdef DT_WHT
+       /*
+        * Whited-out files don't really exist.  However, there's stat(2) file
+        * mask for them, so we set it so that programs (i.e., find) don't have
+        * to test FTS_W separately from other file types.
+        */
+       if (dp != NULL && dp->d_type == DT_WHT) {
+               memset(sbp, 0, sizeof(struct stat));
+               sbp->st_mode = S_IFWHT;
+               return (FTS_W);
+       }
+#endif
+
        /*
         * If doing a logical walk, or application requested FTS_FOLLOW, do
         * a stat(2).  If that fails, check for a non-existent symlink.  If
index 55194db..3aa3666 100644 (file)
--- a/io/fts.h
+++ b/io/fts.h
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- *     @(#)fts.h       8.1 (Berkeley) 6/2/93
+ *     @(#)fts.h       8.3 (Berkeley) 8/14/94
  */
 
 #ifndef        _FTS_H
 #define        _FTS_H 1
 
-#include <sys/cdefs.h>
+#include <features.h>
 #include <sys/types.h>
 
 typedef struct {
@@ -50,17 +50,18 @@ typedef struct {
        int fts_nitems;                 /* elements in the sort array */
        int (*fts_compar) __P((const void *, const void *)); /* compare fn */
 
-#define        FTS_COMFOLLOW   0x001           /* follow command line symlinks */
-#define        FTS_LOGICAL     0x002           /* logical walk */
-#define        FTS_NOCHDIR     0x004           /* don't change directories */
-#define        FTS_NOSTAT      0x008           /* don't get stat info */
-#define        FTS_PHYSICAL    0x010           /* physical walk */
-#define        FTS_SEEDOT      0x020           /* return dot and dot-dot */
-#define        FTS_XDEV        0x040           /* don't cross devices */
-#define        FTS_OPTIONMASK  0x07f           /* valid user option mask */
+#define        FTS_COMFOLLOW   0x0001          /* follow command line symlinks */
+#define        FTS_LOGICAL     0x0002          /* logical walk */
+#define        FTS_NOCHDIR     0x0004          /* don't change directories */
+#define        FTS_NOSTAT      0x0008          /* don't get stat info */
+#define        FTS_PHYSICAL    0x0010          /* physical walk */
+#define        FTS_SEEDOT      0x0020          /* return dot and dot-dot */
+#define        FTS_XDEV        0x0040          /* don't cross devices */
+#define FTS_WHITEOUT   0x0080          /* return whiteout information */
+#define        FTS_OPTIONMASK  0x00ff          /* valid user option mask */
 
-#define        FTS_NAMEONLY    0x080           /* (private) child names only */
-#define        FTS_STOP        0x100           /* (private) unrecoverable error */
+#define        FTS_NAMEONLY    0x0100          /* (private) child names only */
+#define        FTS_STOP        0x0200          /* (private) unrecoverable error */
        int fts_options;                /* fts_open options, global flags */
 } FTS;
 
@@ -98,6 +99,7 @@ typedef struct _ftsent {
 #define        FTS_NSOK        11              /* no stat(2) requested */
 #define        FTS_SL          12              /* symbolic link */
 #define        FTS_SLNONE      13              /* symbolic link without target */
+#define FTS_W          14              /* whiteout object */
        u_short fts_info;               /* user flags for FTSENT structure */
 
 #define        FTS_DONTCHDIR    0x01           /* don't chdir .. to the parent */
index e8ae15b..7381033 100644 (file)
--- a/libc.map
+++ b/libc.map
@@ -474,7 +474,7 @@ GLIBC_2.1 {
     # global variables
     _IO_2_1_stdin_; _IO_2_1_stdout_; _IO_2_1_stderr_;
     __gconv_alias_db; __gconv_nmodules; __gconv_modules_db;
-    _dl_profile;
+    _dl_profile; __libc_stack_end;
 
     # This is for ix86 only.
     _fp_hw;
index c568296..ab6b66a 100644 (file)
@@ -288,7 +288,7 @@ int __pthread_manager(void *reqfd);
 void __pthread_manager_sighandler(int sig);
 void __pthread_reset_main_thread(void);
 void __fresetlockfiles(void);
-
+void __pthread_manager_adjust_prio(int thread_prio);
 
 /* Prototypes for the function without cancelation support when the
    normal version has it.  */
index e7de399..c962532 100644 (file)
@@ -93,6 +93,8 @@ int __pthread_manager(void *arg)
   sigfillset(&mask);
   sigdelset(&mask, PTHREAD_SIG_RESTART);
   sigprocmask(SIG_SETMASK, &mask, NULL);
+  /* Raise our priority to match that of main thread */
+  __pthread_manager_adjust_prio(__pthread_main_thread->p_priority);
   /* Enter server loop */
   while(1) {
     FD_ZERO(&readfds);
@@ -276,6 +278,8 @@ static int pthread_handle_create(pthread_t *thread, const pthread_attr_t *attr,
   new_thread->p_start_args.start_routine = start_routine;
   new_thread->p_start_args.arg = arg;
   new_thread->p_start_args.mask = *mask;
+  /* Raise priority of thread manager if needed */
+  __pthread_manager_adjust_prio(new_thread->p_priority);
   /* Do the cloning */
   pid = __clone(pthread_start_thread, (void **) new_thread,
                 CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND |
@@ -390,10 +394,22 @@ static void pthread_reap_children(void)
   }
 }
 
-/* Free the resources of a thread */
+/* Try to free the resources of a thread when requested by pthread_join
+   or pthread_detach on a terminated thread. */
 
 static void pthread_handle_free(pthread_descr th)
 {
+  pthread_descr t;
+
+  /* Check that the thread th is still there -- pthread_reap_children
+     might have deallocated it already */
+  t = __pthread_main_thread;
+  do {
+    if (t == th) break;
+    t = t->p_nextlive;
+  } while (t != __pthread_main_thread);
+  if (t != th) return;
+
   acquire(th->p_spinlock);
   if (th->p_exited) {
     release(th->p_spinlock);
@@ -455,3 +471,18 @@ void __pthread_manager_sighandler(int sig)
 {
   terminated_children = 1;
 }
+
+/* Adjust priority of thread manager so that it always run at a priority
+   higher than all threads */
+
+void __pthread_manager_adjust_prio(int thread_prio)
+{
+  struct sched_param param;
+
+  if (thread_prio <= __pthread_manager_thread.p_priority) return;
+  param.sched_priority =
+    thread_prio < __sched_get_priority_max(SCHED_FIFO) 
+    ? thread_prio + 1 : thread_prio;
+  __sched_setscheduler(__pthread_manager_thread.p_pid, SCHED_FIFO, &param);
+  __pthread_manager_thread.p_priority = thread_prio;
+}
index d4ebcb8..3b40ac0 100644 (file)
@@ -91,47 +91,49 @@ int __pthread_mutex_lock(pthread_mutex_t * mutex)
 {
   pthread_descr self;
 
-  while(1) {
-    acquire(&mutex->m_spinlock);
-    switch(mutex->m_kind) {
-    case PTHREAD_MUTEX_FAST_NP:
-      if (mutex->m_count == 0) {
-        mutex->m_count = 1;
-        release(&mutex->m_spinlock);
-        return 0;
-      }
-      self = thread_self();
-      break;
-    case PTHREAD_MUTEX_RECURSIVE_NP:
-      self = thread_self();
-      if (mutex->m_count == 0 || mutex->m_owner == self) {
-        mutex->m_count++;
-        mutex->m_owner = self;
-        release(&mutex->m_spinlock);
-        return 0;
-      }
-      break;
-    case PTHREAD_MUTEX_ERRORCHECK_NP:
-      self = thread_self();
-      if (mutex->m_count == 0) {
-       mutex->m_count = 1;
-       mutex->m_owner = self;
-       release(&mutex->m_spinlock);
-       return 0;
-      } else if (mutex->m_owner == self) {
-       release(&mutex->m_spinlock);
-       return EDEADLK;
-      }
-      break;
-    default:
+  acquire(&mutex->m_spinlock);
+  switch(mutex->m_kind) {
+  case PTHREAD_MUTEX_FAST_NP:
+    if (mutex->m_count == 0) {
+      mutex->m_count = 1;
+      release(&mutex->m_spinlock);
+      return 0;
+    }
+    self = thread_self();
+    break;
+  case PTHREAD_MUTEX_RECURSIVE_NP:
+    self = thread_self();
+    if (mutex->m_count == 0 || mutex->m_owner == self) {
+      mutex->m_count++;
+      mutex->m_owner = self;
+      release(&mutex->m_spinlock);
+      return 0;
+    }
+    break;
+  case PTHREAD_MUTEX_ERRORCHECK_NP:
+    self = thread_self();
+    if (mutex->m_count == 0) {
+      mutex->m_count = 1;
+      mutex->m_owner = self;
       release(&mutex->m_spinlock);
-      return EINVAL;
+      return 0;
+    } else if (mutex->m_owner == self) {
+      release(&mutex->m_spinlock);
+      return EDEADLK;
     }
-    /* Suspend ourselves, then try again */
-    enqueue(&mutex->m_waiting, self);
+    break;
+  default:
     release(&mutex->m_spinlock);
-    suspend(self); /* This is not a cancellation point */
+    return EINVAL;
   }
+  /* Suspend ourselves */
+  enqueue(&mutex->m_waiting, self);
+  release(&mutex->m_spinlock);
+  suspend(self); /* This is not a cancellation point */
+  /* Now we own the mutex */
+  ASSERT(mutex->m_count == 1);
+  mutex->m_owner = self;        /* for recursive and errorcheck mutexes */
+  return 0;
 }
 weak_alias (__pthread_mutex_lock, pthread_mutex_lock)
 
@@ -142,30 +144,33 @@ int __pthread_mutex_unlock(pthread_mutex_t * mutex)
   acquire(&mutex->m_spinlock);
   switch (mutex->m_kind) {
   case PTHREAD_MUTEX_FAST_NP:
-    mutex->m_count = 0;
     break;
   case PTHREAD_MUTEX_RECURSIVE_NP:
-    mutex->m_count--;
-    if (mutex->m_count > 0) {
+    if (mutex->m_count >= 2) {
+      mutex->m_count--;
       release(&mutex->m_spinlock);
       return 0;
     }
-    mutex->m_count = 0; /* so that excess unlocks do not break everything */
     break;
   case PTHREAD_MUTEX_ERRORCHECK_NP:
     if (mutex->m_count == 0 || mutex->m_owner != thread_self()) {
       release(&mutex->m_spinlock);
       return EPERM;
     }
-    mutex->m_count = 0;
     break;
   default:
     release(&mutex->m_spinlock);
     return EINVAL;
   }
   th = dequeue(&mutex->m_waiting);
+  /* If no waiters, unlock the mutex */
+  if (th == NULL) mutex->m_count = 0;
   release(&mutex->m_spinlock);
-  if (th != NULL) restart(th);
+  /* If there is a waiter, restart it with the mutex still locked */
+  if (th != NULL) {
+    mutex->m_owner = NULL;      /* we no longer own the mutex */
+    restart(th);
+  }
   return 0;
 }
 weak_alias (__pthread_mutex_unlock, pthread_mutex_unlock)
index 9699b4d..83d1606 100644 (file)
@@ -58,7 +58,8 @@ struct _pthread_descr_struct __pthread_initial_thread = {
 };
 
 /* Descriptor of the manager thread; none of this is used but the error
-   variables and the address for identification.  */
+   variables, the p_pid and p_priority fields,
+   and the address for identification.  */
 
 struct _pthread_descr_struct __pthread_manager_thread = {
   NULL,                       /* pthread_descr p_nextlive */
@@ -108,10 +109,6 @@ int __pthread_manager_request = -1;
 
 int __pthread_manager_reader;
 
-/* PID of thread manager */
-
-static int __pthread_manager_pid;
-
 /* Limits of the thread manager stack */
 
 char *__pthread_manager_thread_bos = NULL;
@@ -203,6 +200,7 @@ static void pthread_initialize(void)
 static int pthread_initialize_manager(void)
 {
   int manager_pipe[2];
+  int pid;
 
   /* If basic initialization not done yet (e.g. we're called from a
      constructor run before our constructor), do it now */
@@ -217,20 +215,19 @@ static int pthread_initialize_manager(void)
     free(__pthread_manager_thread_bos);
     return -1;
   }
-  __pthread_manager_request = manager_pipe[1]; /* writing end */
-  __pthread_manager_reader = manager_pipe[0]; /* reading end */
   /* Start the thread manager */
-  __pthread_manager_pid =
-    __clone(__pthread_manager, (void **) __pthread_manager_thread_tos,
-           CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND,
-           (void *)(long)manager_pipe[0]);
-  if (__pthread_manager_pid == -1) {
+  pid = __clone(__pthread_manager, (void **) __pthread_manager_thread_tos,
+                CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND,
+                (void *)(long)manager_pipe[0]);
+  if (pid == -1) {
     free(__pthread_manager_thread_bos);
     __libc_close(manager_pipe[0]);
     __libc_close(manager_pipe[1]);
-    __pthread_manager_request = -1;
     return -1;
   }
+  __pthread_manager_request = manager_pipe[1]; /* writing end */
+  __pthread_manager_reader = manager_pipe[0]; /* reading end */
+  __pthread_manager_thread.p_pid = pid;
   return 0;
 }
 
@@ -319,6 +316,8 @@ int pthread_setschedparam(pthread_t thread, int policy,
   }
   th->p_priority = policy == SCHED_OTHER ? 0 : param->sched_priority;
   release(&handle->h_spinlock);
+  if (__pthread_manager_request >= 0)
+    __pthread_manager_adjust_prio(th->p_priority);
   return 0;
 }
 
@@ -359,7 +358,7 @@ static void pthread_exit_process(int retcode, void *arg)
     /* Main thread should accumulate times for thread manager and its
        children, so that timings for main thread account for all threads. */
     if (self == __pthread_main_thread)
-      waitpid(__pthread_manager_pid, NULL, __WCLONE);
+      waitpid(__pthread_manager_thread.p_pid, NULL, __WCLONE);
   }
 }
 
@@ -392,7 +391,7 @@ static void pthread_handle_sigcancel(int sig)
     /* Main thread should accumulate times for thread manager and its
        children, so that timings for main thread account for all threads. */
     if (self == __pthread_main_thread)
-      waitpid(__pthread_manager_pid, NULL, __WCLONE);
+      waitpid(__pthread_manager_thread.p_pid, NULL, __WCLONE);
     _exit(__pthread_exit_code);
   }
   if (self->p_canceled && self->p_cancelstate == PTHREAD_CANCEL_ENABLE) {
index 1d079a3..ca45710 100644 (file)
@@ -53,10 +53,10 @@ __BEGIN_DECLS
 /* Structure describing a mount table entry.  */
 struct mntent
   {
-    const char *mnt_fsname;    /* Device or server for filesystem.  */
-    const char *mnt_dir;       /* Directory mounted on.  */
-    const char *mnt_type;      /* Type of filesystem: ufs, nfs, etc.  */
-    const char *mnt_opts;      /* Comma-separated options for fs.  */
+    char *mnt_fsname;          /* Device or server for filesystem.  */
+    char *mnt_dir;             /* Directory mounted on.  */
+    char *mnt_type;            /* Type of filesystem: ufs, nfs, etc.  */
+    char *mnt_opts;            /* Comma-separated options for fs.  */
     int mnt_freq;              /* Dump frequency (in days).  */
     int mnt_passno;            /* Pass number for `fsck'.  */
   };
index cd67c98..d6f3743 100644 (file)
@@ -1,24 +1,30 @@
 /* Test case by Horst von Brand <vonbrand@sleipnir.valparaiso.cl>.  */
-#include <stdio.h> 
-#include <mntent.h> 
+#include <mntent.h>
+#include <stdio.h>
+#include <string.h>
+
+
 int
-main (int argc, char *argv[]) 
-{ 
+main (int argc, char *argv[])
+{
   int result = 0;
-  struct mntent mef =
-  { 
-     "/dev/hda1", "/", "ext2", "defaults", 1, 1 
-  }; 
-  struct mntent *mnt = &mef; 
-  if (hasmntopt (mnt, "defaults"))  
-    printf("Found!\n"); 
-  else 
+  struct mntent mef;
+  struct mntent *mnt = &mef;
+
+  mef.mnt_fsname = strdupa ("/dev/hda1");
+  mef.mnt_dir = strdupa ("/");
+  mef.mnt_type = strdupa ("ext2");
+  mef.mnt_opts = strdupa ("defaults");
+  mef.mnt_freq = 1;
+  mef.mnt_passno = 1;
+
+  if (hasmntopt (mnt, "defaults"))
+    printf ("Found!\n");
+  else
     {
-      printf("Didn't find it\n"); 
+      printf ("Didn't find it\n");
       result = 1;
     }
-   
-   return result; 
-} 
+
+  return result;
+}
index fd6c9d8..2ab2577 100644 (file)
@@ -55,7 +55,7 @@ headers = $(addprefix rpc/,auth.h auth_unix.h clnt.h netdb.h pmap_clnt.h \
          $(rpcsvc:%=rpcsvc/%)
 install-others = $(inst_sysconfdir)/rpc
 generated = $(rpcsvc:%.x=rpcsvc/%.h) $(rpcsvc:%.x=x%.c) $(rpcsvc:%.x=x%.stmp) \
-           $(rpcsvc:%.x=rpcsvc/%.stmp) $rpc-proto.c rpc-proto.d rpcgen
+           $(rpcsvc:%.x=rpcsvc/%.stmp) rpc-proto.c rpc-proto.d rpcgen
 
 routines := auth_none auth_unix authuxprot bindrsvprt \
            clnt_gen clnt_perr clnt_raw clnt_simp clnt_tcp \
index 66b69d0..e6a686e 100644 (file)
@@ -308,10 +308,10 @@ _dl_start_user:
 
 /* Nonzero iff TYPE describes relocation of a PLT entry, so
    PLT entries should not be allowed to define the value.  */
-#define elf_machine_lookup_noplt_p(type) ((type) == R_ARM_JMP_SLOT)
+#define elf_machine_lookup_noplt_p(type) ((type) == R_ARM_JUMP_SLOT)
 
 /* A reloc type used for ld.so cmdline arg lookups to reject PLT entries.  */
-#define ELF_MACHINE_JMP_SLOT   R_ARM_JMP_SLOT
+#define ELF_MACHINE_JMP_SLOT   R_ARM_JUMP_SLOT
 
 /* The i386 never uses Elf32_Rela relocations.  */
 #define ELF_MACHINE_NO_RELA 1
@@ -397,7 +397,7 @@ elf_machine_rel (struct link_map *map, const Elf32_Rel *reloc,
                                                   refsym->st_size));
          break;
        case R_ARM_GLOB_DAT:
-       case R_ARM_JMP_SLOT:
+       case R_ARM_JUMP_SLOT:
 
 #if 0
 #define _HEX(i) for (j=28; j>=0; j-=4) b[7-j/4]="0123456789abcdef"[((int)i>>j)&15];
@@ -429,7 +429,7 @@ __asm__ (" mov r0, #2; mov r1, %0; mov r2, #2; swi 0x00900004; "
 #endif
          *reloc_addr = value;
          break;
-       case R_ARM_32:
+       case R_ARM_ABS32:
          {
 #ifndef RTLD_BOOTSTRAP
           /* This is defined in rtld.c, but nowhere in the static
@@ -450,7 +450,7 @@ __asm__ (" mov r0, #2; mov r1, %0; mov r2, #2; swi 0x00900004; "
            *reloc_addr += value;
            break;
          }
-       case R_ARM_PC26:
+       case R_ARM_PC24:
          *reloc_addr += (value - (Elf32_Addr) reloc_addr);
          break;
        default:
@@ -466,7 +466,7 @@ elf_machine_lazy_rel (struct link_map *map, const Elf32_Rel *reloc)
   Elf32_Addr *const reloc_addr = (void *) (map->l_addr + reloc->r_offset);
   switch (ELF32_R_TYPE (reloc->r_info))
     {
-    case R_ARM_JMP_SLOT:
+    case R_ARM_JUMP_SLOT:
       *reloc_addr += map->l_addr;
       break;
     default:
index 90beb8f..758fb75 100644 (file)
@@ -47,6 +47,8 @@ ElfW(Addr) _dl_base_addr;
 int __libc_enable_secure;
 int __libc_multiple_libcs;     /* Defining this here avoids the inclusion
                                   of init-first.  */
+/* This variable contains the lowest stack address ever used.  */
+void *__libc_stack_end;
 static ElfW(auxv_t) *_dl_auxv;
 unsigned long int _dl_hwcap_mask = HWCAP_IMPORTANT;
 
index 85cdc98..fc63806 100644 (file)
@@ -87,6 +87,8 @@ enum
 #define ST_APPEND      ST_APPEND
   ST_IMMUTABLE = 512,          /* Immutable file.  */
 #define ST_IMMUTABLE   ST_IMMUTABLE
-  ST_NOATIME = 1024            /* Do not update access times.  */
+  ST_NOATIME = 1024,           /* Do not update access times.  */
 #define ST_NOATIME     ST_NOATIME
+  ST_NODIRATIME                        /* Do not update directory access times.  */
+#define ST_NODIRATIME  ST_NODIRATIME
 };
index ef28bc6..de926f4 100644 (file)
@@ -155,6 +155,8 @@ fstatvfs (int fd, struct statvfs *buf)
                      buf->f_flag |= ST_MANDLOCK;
                    else if (strcmp (opt, "noatime") == 0)
                      buf->f_flag |= ST_NOATIME;
+                   else if (strcmp (opt, "nodiratime") == 0)
+                     buf->f_flag |= ST_NODIRATIME;
 
                  /* We can stop looking for more entries.  */
                  break;
index cb27ebf..1add1b2 100644 (file)
@@ -1,4 +1,4 @@
-/* Copyright (C) 1991, 92, 93, 95, 96, 97 Free Software Foundation, Inc.
+/* Copyright (C) 1991, 92, 93, 95, 96, 97, 98 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
 
    The GNU C Library is free software; you can redistribute it and/or
@@ -19,7 +19,7 @@
 #ifndef __NETINET_IP_H
 #define __NETINET_IP_H 1
 
-#include <sys/cdefs.h>
+#include <features.h>
 #include <sys/types.h>
 
 #include <netinet/in.h>
@@ -60,7 +60,9 @@ struct ip_options
     u_int8_t router_alert;
     u_int8_t __pad1;
     u_int8_t __pad2;
+#ifdef __GNUC__
     u_int8_t __data[0];
+#endif
   };
 
 struct iphdr
index c9ace10..589ecbc 100644 (file)
@@ -53,8 +53,10 @@ enum
 #define S_APPEND       S_APPEND
   S_IMMUTABLE = 512,           /* Immutable file.  */
 #define S_IMMUTABLE    S_IMMUTABLE
-  MS_NOATIME = 1024            /* Do not update access times.  */
+  MS_NOATIME = 1024,           /* Do not update access times.  */
 #define MS_NOATIME     MS_NOATIME
+  MS_NODIRATIME = 2048         /* Do not update directory access times.  */
+#define MS_NODIRATIME  MS_NODIRATIME
 };
 
 /* Flags that can be altered by MS_REMOUNT  */