1
0
mirror of https://sourceware.org/git/glibc.git synced 2025-07-28 00:21:52 +03:00
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.
This commit is contained in:
Ulrich Drepper
1998-06-09 15:16:55 +00:00
parent 7646e67e6c
commit bf7997b65c
161 changed files with 6930 additions and 4720 deletions

178
ChangeLog
View File

@ -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> 1998-06-08 21:33 Ulrich Drepper <drepper@cygnus.com>
* localedata/SUPPORTED: Add sk_SK. * localedata/SUPPORTED: Add sk_SK.

View 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 \ 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 \ db_shash db_thread hash hash_auto hash_conv hash_debug \
hash_dup hash_func hash_page hash_rec hash_stat lock \ 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_auto log_compare log_findckp log_get log_put log_rec \
log_register mp_bh mp_fget mp_fopen mp_fput mp_fset \ log_register mp_bh mp_fget mp_fopen mp_fput mp_fset \
mp_open mp_pr mp_region mp_sync mutex txn txn_auto \ mp_open mp_pr mp_region mp_sync mutex txn txn_auto \

View File

@ -1,7 +1,7 @@
/*- /*-
* See the file LICENSE for redistribution information. * See the file LICENSE for redistribution information.
* *
* Copyright (c) 1996, 1997 * Copyright (c) 1996, 1997, 1998
* Sleepycat Software. All rights reserved. * Sleepycat Software. All rights reserved.
*/ */
/* /*
@ -47,18 +47,13 @@
#include "config.h" #include "config.h"
#ifndef lint #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 */ #endif /* not lint */
#ifndef NO_SYSTEM_INCLUDES #ifndef NO_SYSTEM_INCLUDES
#include <sys/types.h> #include <sys/types.h>
#include <sys/mman.h>
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h> #include <string.h>
#include <unistd.h>
#endif #endif
#include "db_int.h" #include "db_int.h"
@ -104,12 +99,12 @@ __bam_close(dbp)
* __bam_sync -- * __bam_sync --
* Sync the btree to disk. * Sync the btree to disk.
* *
* PUBLIC: int __bam_sync __P((DB *, int)); * PUBLIC: int __bam_sync __P((DB *, u_int32_t));
*/ */
int int
__bam_sync(argdbp, flags) __bam_sync(argdbp, flags)
DB *argdbp; DB *argdbp;
int flags; u_int32_t flags;
{ {
DB *dbp; DB *dbp;
int ret; int ret;
@ -146,7 +141,7 @@ __bam_upstat(dbp)
BTMETA *meta; BTMETA *meta;
DB_LOCK metalock; DB_LOCK metalock;
db_pgno_t pgno; 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 * 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) { if (__bam_pget(dbp, (PAGE **)&meta, &pgno, 0) == 0) {
/* Log the change. */ /* Log the change. */
if (DB_LOGGING(dbp) && if (DB_LOGGING(dbp) &&
(ret = __db_noop_log(dbp->dbenv->lg_info, dbp->txn, __db_noop_log(dbp->dbenv->lg_info, dbp->txn, &LSN(meta), 0,
&LSN(meta), 0)) == 0) dbp->log_fileid, PGNO_METADATA, &LSN(meta)) != 0)
goto err; goto err;
/* Update the statistics. */ /* Update the statistics. */

View File

@ -1,7 +1,7 @@
/*- /*-
* See the file LICENSE for redistribution information. * See the file LICENSE for redistribution information.
* *
* Copyright (c) 1996, 1997 * Copyright (c) 1996, 1997, 1998
* Sleepycat Software. All rights reserved. * Sleepycat Software. All rights reserved.
*/ */
/* /*
@ -47,14 +47,12 @@
#include "config.h" #include "config.h"
#ifndef lint #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 */ #endif /* not lint */
#ifndef NO_SYSTEM_INCLUDES #ifndef NO_SYSTEM_INCLUDES
#include <sys/types.h> #include <sys/types.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h> #include <string.h>
#endif #endif
@ -106,7 +104,6 @@ __bam_cmp(dbp, k1, e)
if (B_TYPE(bk->type) == B_OVERFLOW) if (B_TYPE(bk->type) == B_OVERFLOW)
bo = (BOVERFLOW *)bk; bo = (BOVERFLOW *)bk;
else { else {
memset(&k2, 0, sizeof(k2));
k2.data = bk->data; k2.data = bk->data;
k2.size = bk->len; k2.size = bk->len;
} }
@ -115,7 +112,6 @@ __bam_cmp(dbp, k1, e)
if (B_TYPE(bi->type) == B_OVERFLOW) if (B_TYPE(bi->type) == B_OVERFLOW)
bo = (BOVERFLOW *)(bi->data); bo = (BOVERFLOW *)(bi->data);
else { else {
memset(&k2, 0, sizeof(k2));
k2.data = bi->data; k2.data = bi->data;
k2.size = bi->len; k2.size = bi->len;
} }
@ -139,10 +135,21 @@ __bam_cmp(dbp, k1, e)
* Otherwise, we need a contiguous record so we can hand it * Otherwise, we need a contiguous record so we can hand it
* to the user's routine. * to the user's routine.
*/ */
memset(&k2, 0, sizeof(k2));
if (__db_goff(dbp, &k2, bo->tlen, if (__db_goff(dbp, &k2, bo->tlen,
bo->pgno, &t->bt_rdata.data, &t->bt_rdata.ulen) != 0) bo->pgno, &t->bt_rdata.data, &t->bt_rdata.ulen) != 0) {
abort(); (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)); return ((*t->bt_compare)(k1, &k2));
} }

View File

@ -1,14 +1,14 @@
/*- /*-
* See the file LICENSE for redistribution information. * See the file LICENSE for redistribution information.
* *
* Copyright (c) 1996, 1997 * Copyright (c) 1996, 1997, 1998
* Sleepycat Software. All rights reserved. * Sleepycat Software. All rights reserved.
*/ */
#include "config.h" #include "config.h"
#ifndef lint #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 */ #endif /* not lint */
#ifndef NO_SYSTEM_INCLUDES #ifndef NO_SYSTEM_INCLUDES

View File

@ -1,22 +1,20 @@
/*- /*-
* See the file LICENSE for redistribution information. * See the file LICENSE for redistribution information.
* *
* Copyright (c) 1996, 1997 * Copyright (c) 1996, 1997, 1998
* Sleepycat Software. All rights reserved. * Sleepycat Software. All rights reserved.
*/ */
#include "config.h" #include "config.h"
#ifndef lint #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 */ #endif /* not lint */
#ifndef NO_SYSTEM_INCLUDES #ifndef NO_SYSTEM_INCLUDES
#include <sys/types.h> #include <sys/types.h>
#include <errno.h> #include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h> #include <string.h>
#endif #endif
@ -25,24 +23,30 @@ static const char sccsid[] = "@(#)bt_cursor.c 10.41 (Sleepycat) 1/8/98";
#include "btree.h" #include "btree.h"
static int __bam_c_close __P((DBC *)); 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_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_last __P((DB *, CURSOR *));
static int __bam_c_next __P((DB *, CURSOR *, int)); static int __bam_c_next __P((DB *, CURSOR *, int));
static int __bam_c_physdel __P((DB *, CURSOR *, PAGE *)); static int __bam_c_physdel __P((DB *, CURSOR *, PAGE *));
static int __bam_c_prev __P((DB *, CURSOR *)); static int __bam_c_prev __P((DB *, CURSOR *));
static int __bam_c_put __P((DBC *, DBT *, DBT *, int)); static int __bam_c_put __P((DBC *, DBT *, DBT *, u_int32_t));
static int __bam_c_rget __P((DB *, CURSOR *, DBT *, int)); static int __bam_c_rget __P((DB *, CURSOR *, DBT *, u_int32_t));
static int __bam_c_search __P((DB *, CURSOR *, const DBT *, u_int, int, int *)); static int __bam_c_search
__P((DB *, CURSOR *, const DBT *, u_int32_t, int, int *));
/* Discard the current page/lock held by a cursor. */ /* Discard the current page/lock held by a cursor. */
#undef DISCARD #undef DISCARD
#define DISCARD(dbp, cp) { \ #define DISCARD(dbp, cp) { \
(void)memp_fput(dbp->mpf, (cp)->page, 0); \ if ((cp)->page != NULL) { \
(cp)->page = NULL; \ (void)memp_fput(dbp->mpf, (cp)->page, 0); \
(void)__BT_TLPUT((dbp), (cp)->lock); \ (cp)->page = NULL; \
(cp)->lock = LOCK_INVALID; \ } \
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 * All cursors are queued from the master DB structure. Add the
* cursor to that queue. * cursor to that queue.
*/ */
DB_THREAD_LOCK(dbp); CURSOR_SETUP(dbp);
TAILQ_INSERT_HEAD(&dbp->curs_queue, dbc, links); TAILQ_INSERT_HEAD(&dbp->curs_queue, dbc, links);
DB_THREAD_UNLOCK(dbp); CURSOR_TEARDOWN(dbp);
*dbcp = dbc; *dbcp = dbc;
return (0); return (0);
@ -128,13 +132,6 @@ __bam_c_iclose(dbp, dbc)
CURSOR *cp; CURSOR *cp;
int ret; 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. */ /* If a cursor key was deleted, perform the actual deletion. */
cp = dbc->internal; cp = dbc->internal;
ret = F_ISSET(cp, C_DELETED) ? __bam_c_physdel(dbp, cp, NULL) : 0; 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); (void)__BT_TLPUT(dbp, cp->lock);
/* Remove the cursor from the queue. */ /* Remove the cursor from the queue. */
DB_THREAD_LOCK(dbp); CURSOR_SETUP(dbp);
TAILQ_REMOVE(&dbp->curs_queue, dbc, links); TAILQ_REMOVE(&dbp->curs_queue, dbc, links);
DB_THREAD_UNLOCK(dbp); CURSOR_TEARDOWN(dbp);
/* Discard the structures. */ /* Discard the structures. */
FREE(dbc->internal, sizeof(CURSOR)); FREE(dbc->internal, sizeof(CURSOR));
@ -162,8 +159,9 @@ __bam_c_iclose(dbp, dbc)
static int static int
__bam_c_del(dbc, flags) __bam_c_del(dbc, flags)
DBC *dbc; DBC *dbc;
int flags; u_int32_t flags;
{ {
BTREE *t;
CURSOR *cp; CURSOR *cp;
DB *dbp; DB *dbp;
DB_LOCK lock; DB_LOCK lock;
@ -175,6 +173,7 @@ __bam_c_del(dbc, flags)
DEBUG_LWRITE(dbc->dbp, dbc->txn, "bam_c_del", NULL, NULL, flags); DEBUG_LWRITE(dbc->dbp, dbc->txn, "bam_c_del", NULL, NULL, flags);
cp = dbc->internal; cp = dbc->internal;
h = NULL;
/* Check for invalid flags. */ /* Check for invalid flags. */
if ((ret = __db_cdelchk(dbc->dbp, flags, if ((ret = __db_cdelchk(dbc->dbp, flags,
@ -186,6 +185,7 @@ __bam_c_del(dbc, flags)
return (DB_KEYEMPTY); return (DB_KEYEMPTY);
GETHANDLE(dbc->dbp, dbc->txn, &dbp, ret); GETHANDLE(dbc->dbp, dbc->txn, &dbp, ret);
t = dbp->internal;
/* /*
* We don't physically delete the record until the cursor moves, * 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); (void)__bam_ca_delete(dbp, pgno, indx, NULL, 0);
ret = memp_fput(dbp->mpf, h, DB_MPOOL_DIRTY); ret = memp_fput(dbp->mpf, h, DB_MPOOL_DIRTY);
h = NULL;
err: PUTHANDLE(dbp); /*
* 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: if (h != NULL)
(void)memp_fput(dbp->mpf, h, 0);
PUTHANDLE(dbp);
return (ret); return (ret);
} }
@ -244,14 +257,14 @@ err: PUTHANDLE(dbp);
* __bam_get -- * __bam_get --
* Retrieve a key/data pair from the tree. * 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 int
__bam_get(argdbp, txn, key, data, flags) __bam_get(argdbp, txn, key, data, flags)
DB *argdbp; DB *argdbp;
DB_TXN *txn; DB_TXN *txn;
DBT *key, *data; DBT *key, *data;
int flags; u_int32_t flags;
{ {
DBC dbc; DBC dbc;
CURSOR cp; CURSOR cp;
@ -289,7 +302,7 @@ static int
__bam_c_get(dbc, key, data, flags) __bam_c_get(dbc, key, data, flags)
DBC *dbc; DBC *dbc;
DBT *key, *data; DBT *key, *data;
int flags; u_int32_t flags;
{ {
BTREE *t; BTREE *t;
CURSOR *cp, copy; CURSOR *cp, copy;
@ -448,7 +461,7 @@ __bam_c_rget(dbp, cp, data, flags)
DB *dbp; DB *dbp;
CURSOR *cp; CURSOR *cp;
DBT *data; DBT *data;
int flags; u_int32_t flags;
{ {
BTREE *t; BTREE *t;
DBT dbt; DBT dbt;
@ -491,7 +504,7 @@ static int
__bam_c_put(dbc, key, data, flags) __bam_c_put(dbc, key, data, flags)
DBC *dbc; DBC *dbc;
DBT *key, *data; DBT *key, *data;
int flags; u_int32_t flags;
{ {
BTREE *t; BTREE *t;
CURSOR *cp, copy; CURSOR *cp, copy;
@ -499,7 +512,8 @@ __bam_c_put(dbc, key, data, flags)
DBT dbt; DBT dbt;
db_indx_t indx; db_indx_t indx;
db_pgno_t pgno; db_pgno_t pgno;
int exact, needkey, ret; u_int32_t iiflags;
int exact, needkey, ret, stack;
void *arg; void *arg;
DEBUG_LWRITE(dbc->dbp, dbc->txn, "bam_c_put", DEBUG_LWRITE(dbc->dbp, dbc->txn, "bam_c_put",
@ -524,42 +538,26 @@ __bam_c_put(dbc, key, data, flags)
* To split, we need a valid key for the page. Since it's a cursor, * To split, we need a valid key for the page. Since it's a cursor,
* we have to build one. * we have to build one.
*/ */
stack = 0;
if (0) { if (0) {
split: if (needkey) { split: /* Acquire a copy of a key from the page. */
if (needkey) {
memset(&dbt, 0, sizeof(DBT)); memset(&dbt, 0, sizeof(DBT));
ret = __db_ret(dbp, cp->page, indx, if ((ret = __db_ret(dbp, cp->page, indx,
&dbt, &t->bt_rkey.data, &t->bt_rkey.ulen); &dbt, &t->bt_rkey.data, &t->bt_rkey.ulen)) != 0)
DISCARD(dbp, cp);
if (ret)
goto err; goto err;
arg = &dbt; arg = &dbt;
} else { } else
(void)__bam_stkrel(dbp);
arg = key; arg = key;
}
if ((ret = __bam_split(dbp, arg)) != 0)
goto err;
}
/* If there's no key supplied, use the cursor. */ /* Discard any pinned pages. */
if (flags == DB_KEYFIRST || flags == DB_KEYLAST) if (stack) {
needkey = 0; (void)__bam_stkrel(dbp);
else { stack = 0;
needkey = 1; } else
if (cp->dpgno == PGNO_INVALID) { DISCARD(dbp, cp);
pgno = cp->pgno;
indx = cp->indx; if ((ret = __bam_split(dbp, arg)) != 0)
} else {
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; goto err;
} }
@ -568,28 +566,61 @@ split: if (needkey) {
case DB_AFTER: case DB_AFTER:
case DB_BEFORE: case DB_BEFORE:
case DB_CURRENT: case DB_CURRENT:
needkey = 1;
if (cp->dpgno == PGNO_INVALID) {
pgno = cp->pgno;
indx = cp->indx;
} else {
pgno = cp->dpgno;
indx = cp->dindx;
}
/*
* 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;
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, if ((ret = __bam_iitem(dbp, &cp->page,
&indx, key, data, flags, 0)) == DB_NEEDSPLIT) &indx, key, data, flags, iiflags)) == DB_NEEDSPLIT)
goto split; goto split;
break; break;
case DB_KEYFIRST: case DB_KEYFIRST:
exact = 0; exact = needkey = 0;
if ((ret = if ((ret =
__bam_c_search(dbp, cp, key, S_KEYFIRST, 0, &exact)) != 0) __bam_c_search(dbp, cp, key, S_KEYFIRST, 0, &exact)) != 0)
goto err; goto err;
stack = 1;
indx = cp->dpgno == PGNO_INVALID ? cp->indx : cp->dindx; indx = cp->dpgno == PGNO_INVALID ? cp->indx : cp->dindx;
if ((ret = __bam_iitem(dbp, &cp->page, &indx, key, if ((ret = __bam_iitem(dbp, &cp->page, &indx, key,
data, DB_BEFORE, exact ? 0 : BI_NEWKEY)) == DB_NEEDSPLIT) data, DB_BEFORE, exact ? 0 : BI_NEWKEY)) == DB_NEEDSPLIT)
goto split; goto split;
if (ret)
goto err;
break; break;
case DB_KEYLAST: case DB_KEYLAST:
exact = 0; exact = needkey = 0;
if ((ret = if ((ret =
__bam_c_search(dbp, cp, key, S_KEYLAST, 0, &exact)) != 0) __bam_c_search(dbp, cp, key, S_KEYLAST, 0, &exact)) != 0)
goto err; goto err;
stack = 1;
indx = cp->dpgno == PGNO_INVALID ? cp->indx : cp->dindx; indx = cp->dpgno == PGNO_INVALID ? cp->indx : cp->dindx;
if ((ret = __bam_iitem(dbp, &cp->page, &indx, key, if ((ret = __bam_iitem(dbp, &cp->page, &indx, key,
@ -623,13 +654,27 @@ split: if (needkey) {
if (copy.lock != LOCK_INVALID) if (copy.lock != LOCK_INVALID)
(void)__BT_TLPUT(dbp, copy.lock); (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) { if (0) {
err: if (cp->page != NULL) err: /* Discard any pinned pages. */
(void)memp_fput(dbp->mpf, cp->page, 0); if (stack)
if (cp->lock != LOCK_INVALID) (void)__bam_stkrel(dbp);
(void)__BT_TLPUT(dbp, cp->lock); else
DISCARD(dbp, cp);
*cp = copy; *cp = copy;
} }
@ -976,7 +1021,7 @@ __bam_c_search(dbp, cp, key, flags, isrecno, exactp)
DB *dbp; DB *dbp;
CURSOR *cp; CURSOR *cp;
const DBT *key; const DBT *key;
u_int flags; u_int32_t flags;
int isrecno, *exactp; int isrecno, *exactp;
{ {
BTREE *t; BTREE *t;
@ -1032,6 +1077,18 @@ __bam_c_search(dbp, cp, key, flags, isrecno, exactp)
} else } else
if ((ret = __bam_c_next(dbp, cp, 0)) != 0) if ((ret = __bam_c_next(dbp, cp, 0)) != 0)
return (ret); 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); return (0);
} }
@ -1101,7 +1158,7 @@ __bam_cprint(dbp)
CURSOR *cp; CURSOR *cp;
DBC *dbc; DBC *dbc;
DB_THREAD_LOCK(dbp); CURSOR_SETUP(dbp);
for (dbc = TAILQ_FIRST(&dbp->curs_queue); for (dbc = TAILQ_FIRST(&dbp->curs_queue);
dbc != NULL; dbc = TAILQ_NEXT(dbc, links)) { dbc != NULL; dbc = TAILQ_NEXT(dbc, links)) {
cp = (CURSOR *)dbc->internal; cp = (CURSOR *)dbc->internal;
@ -1113,7 +1170,8 @@ __bam_cprint(dbp)
fprintf(stderr, "(deleted)"); fprintf(stderr, "(deleted)");
fprintf(stderr, "\n"); fprintf(stderr, "\n");
} }
DB_THREAD_UNLOCK(dbp); CURSOR_TEARDOWN(dbp);
return (0); return (0);
} }
#endif /* DEBUG */ #endif /* DEBUG */
@ -1135,7 +1193,7 @@ __bam_ca_delete(dbp, pgno, indx, curs, key_delete)
{ {
DBC *dbc; DBC *dbc;
CURSOR *cp; 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 * 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 * 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. * 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); for (count = 0, dbc = TAILQ_FIRST(&dbp->curs_queue);
dbc != NULL; dbc = TAILQ_NEXT(dbc, links)) { dbc != NULL; dbc = TAILQ_NEXT(dbc, links)) {
cp = (CURSOR *)dbc->internal; cp = (CURSOR *)dbc->internal;
@ -1180,8 +1237,8 @@ __bam_ca_delete(dbp, pgno, indx, curs, key_delete)
F_SET(cp, C_DELETED); F_SET(cp, C_DELETED);
} }
} }
CURSOR_TEARDOWN(dbp);
DB_THREAD_UNLOCK(dbp);
return (count); 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)); * PUBLIC: void __bam_ca_di __P((DB *, db_pgno_t, u_int32_t, int));
*/ */
void void
__bam_ca_di(dbp, pgno, indx, value) __bam_ca_di(dbp, pgno, indx, adjust)
DB *dbp; DB *dbp;
db_pgno_t pgno; db_pgno_t pgno;
u_int32_t indx; u_int32_t indx;
int value; int adjust;
{ {
CURSOR *cp; CURSOR *cp;
DBC *dbc; DBC *dbc;
@ -1208,16 +1265,16 @@ __bam_ca_di(dbp, pgno, indx, value)
/* /*
* Adjust the cursors. See the comment in __bam_ca_delete(). * Adjust the cursors. See the comment in __bam_ca_delete().
*/ */
DB_THREAD_LOCK(dbp); CURSOR_SETUP(dbp);
for (dbc = TAILQ_FIRST(&dbp->curs_queue); for (dbc = TAILQ_FIRST(&dbp->curs_queue);
dbc != NULL; dbc = TAILQ_NEXT(dbc, links)) { dbc != NULL; dbc = TAILQ_NEXT(dbc, links)) {
cp = (CURSOR *)dbc->internal; cp = (CURSOR *)dbc->internal;
if (cp->pgno == pgno && cp->indx >= indx) if (cp->pgno == pgno && cp->indx >= indx)
cp->indx += value; cp->indx += adjust;
if (cp->dpgno == pgno && cp->dindx >= indx) 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 * No need to test duplicates, this only gets called when moving
* leaf page data items onto a duplicates page. * leaf page data items onto a duplicates page.
*/ */
DB_THREAD_LOCK(dbp); CURSOR_SETUP(dbp);
for (dbc = TAILQ_FIRST(&dbp->curs_queue); for (dbc = TAILQ_FIRST(&dbp->curs_queue);
dbc != NULL; dbc = TAILQ_NEXT(dbc, links)) { dbc != NULL; dbc = TAILQ_NEXT(dbc, links)) {
cp = (CURSOR *)dbc->internal; cp = (CURSOR *)dbc->internal;
@ -1258,7 +1315,7 @@ __bam_ca_dup(dbp, fpgno, first, fi, tpgno, ti)
cp->dindx = 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 * No need to test duplicates, this only gets called when copying
* over the root page with a leaf or internal page. * over the root page with a leaf or internal page.
*/ */
DB_THREAD_LOCK(dbp); CURSOR_SETUP(dbp);
for (dbc = TAILQ_FIRST(&dbp->curs_queue); for (dbc = TAILQ_FIRST(&dbp->curs_queue);
dbc != NULL; dbc = TAILQ_NEXT(dbc, links)) { dbc != NULL; dbc = TAILQ_NEXT(dbc, links)) {
cp = (CURSOR *)dbc->internal; cp = (CURSOR *)dbc->internal;
if (cp->pgno == fpgno) if (cp->pgno == fpgno)
cp->pgno = tpgno; 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 * for the cursor as it may have been changed by other cursor update
* routines as the item was deleted/inserted. * routines as the item was deleted/inserted.
*/ */
DB_THREAD_LOCK(dbp); CURSOR_SETUP(dbp);
switch (pass) { switch (pass) {
case REPLACE_SETUP: /* Setup. */ case REPLACE_SETUP: /* Setup. */
for (dbc = TAILQ_FIRST(&dbp->curs_queue); for (dbc = TAILQ_FIRST(&dbp->curs_queue);
@ -1372,7 +1429,7 @@ __bam_ca_replace(dbp, pgno, indx, pass)
} }
break; 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 * the cursor is on the right page, it is decremented by the number of
* records split to the left page. * records split to the left page.
*/ */
DB_THREAD_LOCK(dbp); CURSOR_SETUP(dbp);
for (dbc = TAILQ_FIRST(&dbp->curs_queue); for (dbc = TAILQ_FIRST(&dbp->curs_queue);
dbc != NULL; dbc = TAILQ_NEXT(dbc, links)) { dbc != NULL; dbc = TAILQ_NEXT(dbc, links)) {
cp = (CURSOR *)dbc->internal; cp = (CURSOR *)dbc->internal;
@ -1427,7 +1484,7 @@ __bam_ca_split(dbp, ppgno, lpgno, rpgno, split_indx, cleft)
cp->dindx -= split_indx; cp->dindx -= split_indx;
} }
} }
DB_THREAD_UNLOCK(dbp); CURSOR_TEARDOWN(dbp);
} }
/* /*
@ -1440,16 +1497,17 @@ __bam_c_physdel(dbp, cp, h)
CURSOR *cp; CURSOR *cp;
PAGE *h; PAGE *h;
{ {
enum { DELETE_ITEM, DELETE_PAGE, NOTHING_FURTHER } cmd;
BOVERFLOW bo; BOVERFLOW bo;
BTREE *t; BTREE *t;
DBT dbt; DBT dbt;
DB_LOCK lock; DB_LOCK lock;
db_indx_t indx; db_indx_t indx;
db_pgno_t pgno, next_pgno, prev_pgno; db_pgno_t pgno, next_pgno, prev_pgno;
int local, normal, ret; int delete_page, local_page, ret;
t = dbp->internal; t = dbp->internal;
ret = 0; delete_page = ret = 0;
/* Figure out what we're deleting. */ /* Figure out what we're deleting. */
if (cp->dpgno == PGNO_INVALID) { if (cp->dpgno == PGNO_INVALID) {
@ -1476,9 +1534,9 @@ __bam_c_physdel(dbp, cp, h)
return (ret); return (ret);
if ((ret = __bam_pget(dbp, &h, &pgno, 0)) != 0) if ((ret = __bam_pget(dbp, &h, &pgno, 0)) != 0)
return (ret); return (ret);
local = 1; local_page = 1;
} else } else
local = 0; local_page = 0;
/* /*
* If we're deleting a duplicate entry and there are other duplicate * 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 && if (NUM_ENT(h) == 1 &&
prev_pgno == PGNO_INVALID && next_pgno == PGNO_INVALID) prev_pgno == PGNO_INVALID && next_pgno == PGNO_INVALID)
normal = 1; cmd = DELETE_PAGE;
else { else {
normal = 0; cmd = DELETE_ITEM;
/* Delete the duplicate. */ /* Delete the duplicate. */
if ((ret = __db_drem(dbp, &h, indx, __bam_free)) != 0) 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) || if ((h != NULL && pgno == h->pgno) ||
prev_pgno != PGNO_INVALID) 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) if (h != NULL)
(void)memp_fput(dbp->mpf, h, 0); (void)memp_fput(dbp->mpf, h, 0);
(void)__BT_TLPUT(dbp, lock); (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 = if ((ret =
__bam_lget(dbp, 0, cp->pgno, DB_LOCK_WRITE, &lock)) != 0) __bam_lget(dbp, 0, cp->pgno, DB_LOCK_WRITE, &lock)) != 0)
goto err; goto err;
@ -1555,11 +1622,10 @@ __bam_c_physdel(dbp, cp, h)
(void)__BT_TLPUT(dbp, lock); (void)__BT_TLPUT(dbp, lock);
goto err; goto err;
} }
local = 1; local_page = 1;
/* Switch to the parent page's entry. */
indx = cp->indx; indx = cp->indx;
if (normal)
if (cmd == DELETE_PAGE)
goto btd; goto btd;
/* /*
@ -1582,47 +1648,60 @@ __bam_c_physdel(dbp, cp, h)
goto done; goto done;
} }
/* Otherwise, do a normal btree delete. */ btd: /*
btd: if ((ret = __bam_ditem(dbp, h, indx)) != 0) * If the page is going to be emptied, delete it. To delete a leaf
goto err; * page we need a copy of a key from the page. We use the 0th page
if ((ret = __bam_ditem(dbp, h, indx)) != 0) * index since it's the last key that the page held.
goto err; *
* We malloc the page information instead of using the return key/data
/* * memory because we've already set them -- the reason we've already
* If the page is empty, delete it. To delete a leaf page we need a * set them is because we're (potentially) about to do a reverse split,
* copy of a key from the page. We use the first one that was there, * which would make our saved page information useless.
* 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.
* *
* XXX * XXX
* The following operations to delete a page might deadlock. I think * 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 * 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 * closing cursors because we've already deadlocked and want to call
* txn_abort(). If we fail due to deadlock, we'll leave an locked * txn_abort(). If we fail due to deadlock, we leave a locked empty
* empty page in the tree, which won't be empty long because we're * page in the tree, which won't be empty long because we're going to
* going to undo the delete. * 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)); memset(&dbt, 0, sizeof(DBT));
dbt.flags = DB_DBT_MALLOC | DB_DBT_INTERNAL; dbt.flags = DB_DBT_MALLOC | DB_DBT_INTERNAL;
if ((ret = __db_ret(dbp, h, 0, &dbt, NULL, NULL)) != 0) if ((ret = __db_ret(dbp, h, 0, &dbt, NULL, NULL)) != 0)
goto err; goto err;
delete_page = 1;
if (local) {
(void)memp_fput(dbp->mpf, h, 0);
(void)__BT_TLPUT(dbp, lock);
local = 0;
}
ret = __bam_dpage(dbp, &dbt);
__db_free(dbt.data);
} }
/*
* 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;
/* 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: err:
done: if (local) { done: if (delete_page)
__db_free(dbt.data);
if (local_page) {
(void)memp_fput(dbp->mpf, h, 0); (void)memp_fput(dbp->mpf, h, 0);
(void)__BT_TLPUT(dbp, lock); (void)__BT_TLPUT(dbp, lock);
} }
@ -1631,3 +1710,43 @@ done: if (local) {
++t->lstat.bt_deleted; ++t->lstat.bt_deleted;
return (ret); 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);
}

View File

@ -1,7 +1,7 @@
/*- /*-
* See the file LICENSE for redistribution information. * See the file LICENSE for redistribution information.
* *
* Copyright (c) 1996, 1997 * Copyright (c) 1996, 1997, 1998
* Sleepycat Software. All rights reserved. * Sleepycat Software. All rights reserved.
*/ */
/* /*
@ -47,13 +47,12 @@
#include "config.h" #include "config.h"
#ifndef lint #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 */ #endif /* not lint */
#ifndef NO_SYSTEM_INCLUDES #ifndef NO_SYSTEM_INCLUDES
#include <sys/types.h> #include <sys/types.h>
#include <stdio.h>
#include <string.h> #include <string.h>
#endif #endif
@ -67,14 +66,14 @@ static int __bam_dpages __P((DB *, BTREE *));
* __bam_delete -- * __bam_delete --
* Delete the items referenced by a key. * 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 int
__bam_delete(argdbp, txn, key, flags) __bam_delete(argdbp, txn, key, flags)
DB *argdbp; DB *argdbp;
DB_TXN *txn; DB_TXN *txn;
DBT *key; DBT *key;
int flags; u_int32_t flags;
{ {
BTREE *t; BTREE *t;
DB *dbp; DB *dbp;
@ -87,8 +86,8 @@ __bam_delete(argdbp, txn, key, flags)
stack = 0; stack = 0;
/* Check for invalid flags. */ /* Check for invalid flags. */
if ((ret = if ((ret = __db_delchk(argdbp,
__db_delchk(argdbp, flags, F_ISSET(argdbp, DB_AM_RDONLY))) != 0) key, flags, F_ISSET(argdbp, DB_AM_RDONLY))) != 0)
return (ret); return (ret);
GETHANDLE(argdbp, txn, &dbp, ret); GETHANDLE(argdbp, txn, &dbp, ret);
@ -107,6 +106,11 @@ __bam_delete(argdbp, txn, key, flags)
break; break;
for (; cnt > 0; --cnt, ++t->lstat.bt_deleted) for (; cnt > 0; --cnt, ++t->lstat.bt_deleted)
if (__bam_ca_delete(dbp, h->pgno, indx, NULL, 1) == 0) { 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) if ((ret = __bam_ditem(dbp, h, indx)) != 0)
goto err; goto err;
if ((ret = __bam_ditem(dbp, h, indx)) != 0) if ((ret = __bam_ditem(dbp, h, indx)) != 0)
@ -138,14 +142,14 @@ err: if (stack)
* __ram_delete -- * __ram_delete --
* Delete the items referenced by a key. * 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 int
__ram_delete(argdbp, txn, key, flags) __ram_delete(argdbp, txn, key, flags)
DB *argdbp; DB *argdbp;
DB_TXN *txn; DB_TXN *txn;
DBT *key; DBT *key;
int flags; u_int32_t flags;
{ {
BKEYDATA bk; BKEYDATA bk;
BTREE *t; BTREE *t;
@ -159,8 +163,8 @@ __ram_delete(argdbp, txn, key, flags)
stack = 0; stack = 0;
/* Check for invalid flags. */ /* Check for invalid flags. */
if ((ret = if ((ret = __db_delchk(argdbp,
__db_delchk(argdbp, flags, F_ISSET(argdbp, DB_AM_RDONLY))) != 0) key, flags, F_ISSET(argdbp, DB_AM_RDONLY))) != 0)
return (ret); return (ret);
GETHANDLE(argdbp, txn, &dbp, ret); GETHANDLE(argdbp, txn, &dbp, ret);
@ -284,19 +288,32 @@ __bam_ditem(dbp, h, indx)
case P_LBTREE: case P_LBTREE:
/* /*
* If it's a duplicate key, discard the index and don't touch * If it's a duplicate key, discard the index and don't touch
* the actual page item. This works because no data item can * the actual page item.
* 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 * XXX
* index. * 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 % 2) == 0) {
if (indx > 0 && h->inp[indx] == h->inp[indx - P_INDX]) /*
return (__bam_adjindx(dbp, * Check for a duplicate after us on the page. NOTE:
h, indx, indx - P_INDX, 0)); * 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) && if (indx + P_INDX < (u_int32_t)NUM_ENT(h) &&
h->inp[indx] == h->inp[indx + P_INDX]) h->inp[indx] == h->inp[indx + P_INDX])
return (__bam_adjindx(dbp, return (__bam_adjindx(dbp,
h, indx, indx + O_INDX, 0)); 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 */ /* FALLTHROUGH */
case P_LRECNO: case P_LRECNO:
@ -396,7 +413,8 @@ __bam_dpage(dbp, key)
DB_LOCK lock; DB_LOCK lock;
PAGE *h; PAGE *h;
db_pgno_t pgno; db_pgno_t pgno;
int exact, level, ret; int level; /* !!!: has to hold number of tree levels. */
int exact, ret;
ret = 0; ret = 0;
t = dbp->internal; t = dbp->internal;
@ -527,13 +545,14 @@ __bam_dpages(dbp, t)
goto release; goto release;
/* /*
* If we deleted the next-to-last item from the root page, the tree * If we just deleted the last or next-to-last item from the root page,
* can collapse a level. Try and write lock the remaining root + 1 * the tree can collapse a level. Write lock the last page referenced
* page and copy it onto the root page. If we can't get the lock, * by the root page and copy it over the root page. If we can't get a
* that's okay, the tree just stays a level deeper than we'd like. * write lock, that's okay, the tree just remains a level deeper than
* we'd like.
*/ */
h = epg->page; 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 ? pgno = TYPE(epg->page) == P_IBTREE ?
GET_BINTERNAL(epg->page, 0)->pgno : GET_BINTERNAL(epg->page, 0)->pgno :
GET_RINTERNAL(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); (void)memp_fset(dbp->mpf, epg->page, DB_MPOOL_DIRTY);
/* /*
* Free the last page in that level of the btree and discard * Free the page copied onto the root page and discard its
* the lock. (The call to __bam_free discards our reference * lock. (The call to __bam_free() discards our reference
* to the page.) * 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); (void)__BT_TLPUT(dbp, lock);
++t->lstat.bt_freed;
/* Adjust the cursors. */ /* Adjust the cursors. */
__bam_ca_move(dbp, h->pgno, PGNO_ROOT); __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 * Don't bother checking for errors. We've unlinked the subtree from
* the tree, and there's no possibility of recovery. * 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) if (NUM_ENT(epg->page) != 0)
(void)__bam_ditem(dbp, epg->page, epg->indx); (void)__bam_ditem(dbp, epg->page, epg->indx);
(void)__bam_free(dbp, epg->page); (void)__bam_free(dbp, epg->page);
(void)__BT_TLPUT(dbp, epg->lock); (void)__BT_TLPUT(dbp, epg->lock);
++t->lstat.bt_freed;
} }
return (0); return (0);

View File

@ -1,7 +1,7 @@
/*- /*-
* See the file LICENSE for redistribution information. * See the file LICENSE for redistribution information.
* *
* Copyright (c) 1996, 1997 * Copyright (c) 1996, 1997, 1998
* Sleepycat Software. All rights reserved. * Sleepycat Software. All rights reserved.
*/ */
/* /*
@ -47,7 +47,7 @@
#include "config.h" #include "config.h"
#ifndef lint #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 */ #endif /* not lint */
/* /*
@ -60,21 +60,15 @@ static const char sccsid[] = "@(#)bt_open.c 10.22 (Sleepycat) 1/6/98";
#ifndef NO_SYSTEM_INCLUDES #ifndef NO_SYSTEM_INCLUDES
#include <sys/types.h> #include <sys/types.h>
#include <sys/stat.h>
#include <errno.h> #include <errno.h>
#include <fcntl.h>
#include <limits.h> #include <limits.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h> #include <string.h>
#include <unistd.h>
#endif #endif
#include "db_int.h" #include "db_int.h"
#include "db_page.h" #include "db_page.h"
#include "btree.h" #include "btree.h"
#include "common_ext.h"
static int __bam_keyalloc __P((BTREE *)); static int __bam_keyalloc __P((BTREE *));
static int __bam_setmeta __P((DB *, BTREE *)); static int __bam_setmeta __P((DB *, BTREE *));
@ -295,6 +289,7 @@ __bam_setmeta(dbp, t)
} }
/* Initialize the tree structure metadata information. */ /* Initialize the tree structure metadata information. */
memset(meta, 0, sizeof(BTMETA));
ZERO_LSN(meta->lsn); ZERO_LSN(meta->lsn);
meta->pgno = PGNO_METADATA; meta->pgno = PGNO_METADATA;
meta->magic = DB_BTREEMAGIC; meta->magic = DB_BTREEMAGIC;
@ -303,7 +298,6 @@ __bam_setmeta(dbp, t)
meta->maxkey = t->bt_maxkey; meta->maxkey = t->bt_maxkey;
meta->minkey = t->bt_minkey; meta->minkey = t->bt_minkey;
meta->free = PGNO_INVALID; meta->free = PGNO_INVALID;
meta->flags = 0;
if (dbp->type == DB_RECNO) if (dbp->type == DB_RECNO)
F_SET(meta, BTM_RECNO); F_SET(meta, BTM_RECNO);
if (F_ISSET(dbp, DB_AM_DUP)) if (F_ISSET(dbp, DB_AM_DUP))
@ -314,8 +308,6 @@ __bam_setmeta(dbp, t)
F_SET(meta, BTM_RECNUM); F_SET(meta, BTM_RECNUM);
if (F_ISSET(dbp, DB_RE_RENUMBER)) if (F_ISSET(dbp, DB_RE_RENUMBER))
F_SET(meta, BTM_RENUMBER); F_SET(meta, BTM_RENUMBER);
meta->re_len = 0;
meta->re_pad = 0;
memcpy(meta->uid, dbp->lock.fileid, DB_FILE_ID_LEN); memcpy(meta->uid, dbp->lock.fileid, DB_FILE_ID_LEN);
/* Create and initialize a root page. */ /* Create and initialize a root page. */

View File

@ -1,7 +1,7 @@
/*- /*-
* See the file LICENSE for redistribution information. * See the file LICENSE for redistribution information.
* *
* Copyright (c) 1996, 1997 * Copyright (c) 1996, 1997, 1998
* Sleepycat Software. All rights reserved. * Sleepycat Software. All rights reserved.
*/ */
/* /*
@ -47,14 +47,13 @@
#include "config.h" #include "config.h"
#ifndef lint #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 */ #endif /* not lint */
#ifndef NO_SYSTEM_INCLUDES #ifndef NO_SYSTEM_INCLUDES
#include <sys/types.h> #include <sys/types.h>
#include <errno.h> #include <errno.h>
#include <stdio.h>
#include <string.h> #include <string.h>
#endif #endif
@ -142,7 +141,8 @@ __bam_free(dbp, h)
DBT ldbt; DBT ldbt;
DB_LOCK metalock; DB_LOCK metalock;
db_pgno_t pgno; 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 * 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 * fail, then we need to put the page with which we were called
* back because our caller assumes we take care of it. * back because our caller assumes we take care of it.
*/ */
is_dirty = 0; dirty_flag = 0;
pgno = PGNO_METADATA; pgno = PGNO_METADATA;
if ((ret = __bam_lget(dbp, 0, pgno, DB_LOCK_WRITE, &metalock)) != 0) if ((ret = __bam_lget(dbp, 0, pgno, DB_LOCK_WRITE, &metalock)) != 0)
goto err; goto err;
@ -178,7 +178,7 @@ __bam_free(dbp, h)
* The page should have nothing interesting on it, re-initialize it, * The page should have nothing interesting on it, re-initialize it,
* leaving only the page number and the LSN. * leaving only the page number and the LSN.
*/ */
#ifdef DEBUG #ifdef DIAGNOSTIC
{ db_pgno_t __pgno; DB_LSN __lsn; { db_pgno_t __pgno; DB_LSN __lsn;
__pgno = h->pgno; __pgno = h->pgno;
__lsn = h->lsn; __lsn = h->lsn;
@ -198,8 +198,8 @@ __bam_free(dbp, h)
ret = t_ret; ret = t_ret;
/* Discard the caller's page reference. */ /* Discard the caller's page reference. */
is_dirty = DB_MPOOL_DIRTY; dirty_flag = DB_MPOOL_DIRTY;
err: if ((t_ret = memp_fput(dbp->mpf, h, is_dirty)) != 0 && ret == 0) err: if ((t_ret = memp_fput(dbp->mpf, h, dirty_flag)) != 0 && ret == 0)
ret = t_ret; ret = t_ret;
/* /*
@ -248,8 +248,10 @@ __bam_lget(dbp, do_couple, pgno, mode, lockp)
u_int32_t locker; u_int32_t locker;
int ret; int ret;
if (!F_ISSET(dbp, DB_AM_LOCKING)) if (!F_ISSET(dbp, DB_AM_LOCKING)) {
*lockp = LOCK_INVALID;
return (0); return (0);
}
locker = dbp->txn == NULL ? dbp->locker : dbp->txn->txnid; locker = dbp->txn == NULL ? dbp->locker : dbp->txn->txnid;
dbp->lock.pgno = pgno; dbp->lock.pgno = pgno;
@ -300,15 +302,15 @@ __bam_lput(dbp, lock)
* __bam_pget -- * __bam_pget --
* The standard page get call. * 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 int
__bam_pget(dbp, hp, pgnop, mflags) __bam_pget(dbp, hp, pgnop, mpool_flags)
DB *dbp; DB *dbp;
PAGE **hp; PAGE **hp;
db_pgno_t *pgnop; db_pgno_t *pgnop;
int mflags; u_int32_t mpool_flags;
{ {
return (memp_fget((dbp)->mpf, return (memp_fget((dbp)->mpf,
pgnop, mflags, hp) == 0 ? 0 : __db_pgerr(dbp, *pgnop)); pgnop, mpool_flags, hp) == 0 ? 0 : __db_pgerr(dbp, *pgnop));
} }

View File

@ -1,7 +1,7 @@
/*- /*-
* See the file LICENSE for redistribution information. * See the file LICENSE for redistribution information.
* *
* Copyright (c) 1996, 1997 * Copyright (c) 1996, 1997, 1998
* Sleepycat Software. All rights reserved. * Sleepycat Software. All rights reserved.
*/ */
/* /*
@ -47,15 +47,13 @@
#include "config.h" #include "config.h"
#ifndef lint #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 */ #endif /* not lint */
#ifndef NO_SYSTEM_INCLUDES #ifndef NO_SYSTEM_INCLUDES
#include <sys/types.h> #include <sys/types.h>
#include <errno.h> #include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h> #include <string.h>
#endif #endif
@ -75,21 +73,22 @@ static u_int32_t __bam_partsize __P((DBT *, PAGE *, u_int32_t));
* __bam_put -- * __bam_put --
* Add a new key/data pair or replace an existing pair (btree). * 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 int
__bam_put(argdbp, txn, key, data, flags) __bam_put(argdbp, txn, key, data, flags)
DB *argdbp; DB *argdbp;
DB_TXN *txn; DB_TXN *txn;
DBT *key, *data; DBT *key, *data;
int flags; u_int32_t flags;
{ {
BTREE *t; BTREE *t;
CURSOR c; CURSOR c;
DB *dbp; DB *dbp;
PAGE *h; PAGE *h;
db_indx_t indx; 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); 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 * 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. * a set of duplicates, and we simply append a new one to the set.
*/ */
isdeleted = replace = 0; isdeleted = 0;
if (exact) { if (exact) {
if ((ret = __bam_isdeleted(dbp, h, indx, &isdeleted)) != 0) if ((ret = __bam_isdeleted(dbp, h, indx, &isdeleted)) != 0)
goto err; goto err;
if (isdeleted) { if (isdeleted)
replace = 1;
__bam_ca_replace(dbp, h->pgno, indx, REPLACE_SETUP); __bam_ca_replace(dbp, h->pgno, indx, REPLACE_SETUP);
} else else
if (flags == DB_NOOVERWRITE) { if (flags == DB_NOOVERWRITE) {
ret = DB_KEYEXIST; ret = DB_KEYEXIST;
goto err; goto err;
@ -179,42 +177,38 @@ retry: /*
t->bt_csp->page = h = c.page; t->bt_csp->page = h = c.page;
indx = c.dindx; indx = c.dindx;
} }
iflags = DB_AFTER; insert_flags = DB_AFTER;
} else } else
iflags = DB_CURRENT; insert_flags = DB_CURRENT;
} else } else
iflags = DB_BEFORE; insert_flags = DB_BEFORE;
/* /*
* The pages we're using may be modified by __bam_iitem(), so make * The pages we're using may be modified by __bam_iitem(), so make
* sure we reset the stack. * sure we reset the stack.
*/ */
ret = __bam_iitem(dbp, iitem_flags = 0;
&h, &indx, key, data, iflags, newkey ? BI_NEWKEY : 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->page = h;
t->bt_csp->indx = indx; t->bt_csp->indx = indx;
switch (ret) { switch (ret) {
case 0: case 0:
/* /* Done. Clean up the cursor. */
* Done. Clean up the cursor, and, if we're doing record if (isdeleted)
* numbers, adjust the internal page counts.
*/
if (replace)
__bam_ca_replace(dbp, h->pgno, indx, REPLACE_SUCCESS); __bam_ca_replace(dbp, h->pgno, indx, REPLACE_SUCCESS);
if (!replace && F_ISSET(dbp, DB_BT_RECNUM))
ret = __bam_adjust(dbp, t, 1);
break; break;
case DB_NEEDSPLIT: case DB_NEEDSPLIT:
/* /*
* We have to split the page. Back out the cursor setup, * We have to split the page. Back out the cursor setup,
* discard the stack of pages, and do the split. * discard the stack of pages, and do the split.
*/ */
if (replace) { if (isdeleted)
replace = 0;
__bam_ca_replace(dbp, h->pgno, indx, REPLACE_FAILED); __bam_ca_replace(dbp, h->pgno, indx, REPLACE_FAILED);
}
(void)__bam_stkrel(dbp); (void)__bam_stkrel(dbp);
stack = 0; stack = 0;
@ -225,7 +219,7 @@ retry: /*
goto retry; goto retry;
/* NOTREACHED */ /* NOTREACHED */
default: default:
if (replace) if (isdeleted)
__bam_ca_replace(dbp, h->pgno, indx, REPLACE_FAILED); __bam_ca_replace(dbp, h->pgno, indx, REPLACE_FAILED);
break; break;
} }
@ -393,7 +387,8 @@ __bam_lookup(dbp, key, exactp)
for (indx = 0; for (indx = 0;
indx < (db_indx_t)(NUM_ENT(h) - P_INDX) && indx < (db_indx_t)(NUM_ENT(h) - P_INDX) &&
h->inp[indx] == h->inp[indx + P_INDX]; h->inp[indx] == h->inp[indx + P_INDX];
indx += P_INDX); indx += P_INDX)
;
e.indx = indx; e.indx = indx;
} }
goto fast; goto fast;
@ -427,7 +422,7 @@ slow: return (__bam_search(dbp, key, S_INSERT, 1, NULL, exactp));
* Insert an item into the tree. * Insert an item into the tree.
* *
* PUBLIC: int __bam_iitem __P((DB *, * 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 int
__bam_iitem(dbp, hp, indxp, key, data, op, flags) __bam_iitem(dbp, hp, indxp, key, data, op, flags)
@ -435,13 +430,13 @@ __bam_iitem(dbp, hp, indxp, key, data, op, flags)
PAGE **hp; PAGE **hp;
db_indx_t *indxp; db_indx_t *indxp;
DBT *key, *data; DBT *key, *data;
int op, flags; u_int32_t op, flags;
{ {
BTREE *t; BTREE *t;
BKEYDATA *bk; BKEYDATA *bk;
DBT tdbt; DBT tdbt;
PAGE *h; PAGE *h;
db_indx_t indx; db_indx_t indx, nbytes;
u_int32_t data_size, have_bytes, need_bytes, needed; u_int32_t data_size, have_bytes, need_bytes, needed;
int bigkey, bigdata, dupadjust, replace, ret; int bigkey, bigdata, dupadjust, replace, ret;
@ -466,12 +461,27 @@ __bam_iitem(dbp, hp, indxp, key, data, op, flags)
++*indxp; ++*indxp;
/* Remove the current item if it's a DB_CURRENT op. */ /* Remove the current item if it's a DB_CURRENT op. */
if (op == DB_CURRENT && (ret = __db_ditem(dbp, *hp, *indxp, if (op == DB_CURRENT) {
BKEYDATA_SIZE(GET_BKEYDATA(*hp, *indxp)->len))) != 0) bk = GET_BKEYDATA(*hp, *indxp);
return (ret); 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. */ /* 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. */ /* 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. */ case DB_BEFORE: /* 2. Insert a new key/data pair. */
break; break;
default: default:
abort(); return (EINVAL);
} }
/* Add the key. */ /* Add the key. */
@ -638,7 +648,7 @@ __bam_iitem(dbp, hp, indxp, key, data, op, flags)
replace = 1; replace = 1;
break; break;
default: default:
abort(); return (EINVAL);
} }
} }
@ -666,9 +676,8 @@ __bam_iitem(dbp, hp, indxp, key, data, op, flags)
return (ret); return (ret);
} }
++t->lstat.bt_added; if ((ret = memp_fset(dbp->mpf, h, DB_MPOOL_DIRTY)) != 0)
return (ret);
ret = memp_fset(dbp->mpf, h, DB_MPOOL_DIRTY);
/* /*
* If the page is at least 50% full, and we added a duplicate, see if * 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); 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) if (t->bt_recno != NULL)
F_SET(t->bt_recno, RECNO_MODIFIED); F_SET(t->bt_recno, RECNO_MODIFIED);
++t->lstat.bt_added;
return (ret); return (ret);
} }
@ -1036,8 +1061,8 @@ __bam_partial(dbp, dbt, h, indx, nbytes)
BOVERFLOW *bo; BOVERFLOW *bo;
DBT copy; DBT copy;
u_int32_t len, tlen; u_int32_t len, tlen;
int ret;
u_int8_t *p; u_int8_t *p;
int ret;
COMPQUIET(bo, NULL); COMPQUIET(bo, NULL);
@ -1065,59 +1090,62 @@ __bam_partial(dbp, dbt, h, indx, nbytes)
bk->len = 0; 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); memset(t->bt_rdata.data, 0, nbytes);
tlen = 0;
if (B_TYPE(bk->type) == B_OVERFLOW) { 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)); memset(&copy, 0, sizeof(copy));
if ((ret = __db_goff(dbp, &copy, bo->tlen, if ((ret = __db_goff(dbp, &copy, bo->tlen,
bo->pgno, &t->bt_rdata.data, &t->bt_rdata.ulen)) != 0) bo->pgno, &t->bt_rdata.data, &t->bt_rdata.ulen)) != 0)
return (ret); 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: * Copy in any trailing data from the original record.
* If dlen > size, shift the remaining data down. *
* If dlen < size, shift the remaining data up. * 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. * Use memmove(), the regions may overlap.
*/ */
p = t->bt_rdata.data; if (bo->tlen > dbt->doff + dbt->dlen) {
if (bo->tlen > dbt->doff) len = bo->tlen - (dbt->doff + dbt->dlen);
if (dbt->dlen > dbt->size) { if (dbt->dlen != dbt->size)
tlen += len = bo->tlen - memmove(p + dbt->size, p + dbt->dlen, len);
dbt->doff - (dbt->dlen - dbt->size); tlen += len;
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;
/* Copy in the user's data. */ /* Copy in the application provided data. */
memcpy((u_int8_t *)t->bt_rdata.data + dbt->doff, memcpy(p, dbt->data, dbt->size);
dbt->data, dbt->size);
tlen += dbt->size; tlen += dbt->size;
} else { } else {
/* Take up to doff bytes from the record. */ /* Copy in any leading data from the original record. */
memcpy(t->bt_rdata.data, memcpy(t->bt_rdata.data,
bk->data, dbt->doff > bk->len ? bk->len : dbt->doff); 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. */ /* Copy in the application provided data. */
memcpy((u_int8_t *)t->bt_rdata.data + memcpy(p, dbt->data, dbt->size);
dbt->doff, dbt->data, dbt->size);
tlen += dbt->size; tlen += dbt->size;
/* Copy in any remaining data. */ /* Copy in any trailing data from the original record. */
len = dbt->doff + dbt->dlen; len = dbt->doff + dbt->dlen;
if (bk->len > len) { if (bk->len > len) {
memcpy((u_int8_t *)t->bt_rdata.data + dbt->doff + memcpy(p + dbt->size, bk->data + len, bk->len - len);
dbt->size, bk->data + len, bk->len - len);
tlen += bk->len - len; tlen += bk->len - len;
} }
} }

View File

@ -1,23 +1,20 @@
/*- /*-
* See the file LICENSE for redistribution information. * See the file LICENSE for redistribution information.
* *
* Copyright (c) 1996, 1997 * Copyright (c) 1996, 1997, 1998
* Sleepycat Software. All rights reserved. * Sleepycat Software. All rights reserved.
*/ */
#include "config.h" #include "config.h"
#ifndef lint #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 */ #endif /* not lint */
#ifndef NO_SYSTEM_INCLUDES #ifndef NO_SYSTEM_INCLUDES
#include <sys/types.h> #include <sys/types.h>
#include <ctype.h>
#include <errno.h> #include <errno.h>
#include <stddef.h>
#include <stdlib.h>
#include <string.h> #include <string.h>
#endif #endif
@ -27,7 +24,6 @@ static const char sccsid[] = "@(#)bt_rec.c 10.18 (Sleepycat) 12/15/97";
#include "hash.h" #include "hash.h"
#include "btree.h" #include "btree.h"
#include "log.h" #include "log.h"
#include "db_dispatch.h"
#include "common_ext.h" #include "common_ext.h"
/* /*
@ -51,7 +47,7 @@ __bam_pg_alloc_recover(logp, dbtp, lsnp, redo, info)
PAGE *pagep; PAGE *pagep;
DB *file_dbp, *mdbp; DB *file_dbp, *mdbp;
db_pgno_t pgno; 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_PRINT(__bam_pg_alloc_print);
REC_INTRO(__bam_pg_alloc_read); REC_INTRO(__bam_pg_alloc_read);
@ -86,18 +82,17 @@ __bam_pg_alloc_recover(logp, dbtp, lsnp, redo, info)
} }
/* Fix up the allocated page. */ /* Fix up the allocated page. */
created = IS_ZERO_LSN(LSN(pagep));
modified = 0; modified = 0;
cmp_n = log_compare(lsnp, &LSN(pagep)); cmp_n = log_compare(lsnp, &LSN(pagep));
cmp_p = log_compare(&LSN(pagep), &argp->page_lsn); 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. */ /* Need to redo update described. */
P_INIT(pagep, file_dbp->pgsize, P_INIT(pagep, file_dbp->pgsize,
argp->pgno, PGNO_INVALID, PGNO_INVALID, 0, argp->ptype); argp->pgno, PGNO_INVALID, PGNO_INVALID, 0, argp->ptype);
pagep->lsn = *lsnp; pagep->lsn = *lsnp;
modified = 1; modified = 1;
} else if ((created || cmp_n == 0) && !redo) { } else if (cmp_n == 0 && !redo) {
/* Need to undo update described. */ /* Need to undo update described. */
P_INIT(pagep, file_dbp->pgsize, P_INIT(pagep, file_dbp->pgsize,
argp->pgno, PGNO_INVALID, meta->free, 0, P_INVALID); argp->pgno, PGNO_INVALID, meta->free, 0, P_INVALID);

View File

@ -1,14 +1,14 @@
/*- /*-
* See the file LICENSE for redistribution information. * See the file LICENSE for redistribution information.
* *
* Copyright (c) 1997 * Copyright (c) 1997, 1998
* Sleepycat Software. All rights reserved. * Sleepycat Software. All rights reserved.
*/ */
#include "config.h" #include "config.h"
#ifndef lint #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 */ #endif /* not lint */
#ifndef NO_SYSTEM_INCLUDES #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 <errno.h>
#include <limits.h> #include <limits.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h> #include <string.h>
#endif #endif
@ -25,16 +23,17 @@ static const char sccsid[] = "@(#)bt_recno.c 10.26 (Sleepycat) 1/8/98";
#include "db_page.h" #include "db_page.h"
#include "btree.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_close __P((DBC *));
static int __ram_c_del __P((DBC *, int)); static int __ram_c_del __P((DBC *, u_int32_t));
static int __ram_c_get __P((DBC *, DBT *, DBT *, int)); static int __ram_c_get __P((DBC *, DBT *, DBT *, u_int32_t));
static int __ram_c_put __P((DBC *, DBT *, DBT *, int)); static int __ram_c_put __P((DBC *, DBT *, DBT *, u_int32_t));
static int __ram_fmap __P((DB *, db_recno_t)); static int __ram_fmap __P((DB *, db_recno_t));
static int __ram_get __P((DB *, DB_TXN *, DBT *, DBT *, int)); static int __ram_get __P((DB *, DB_TXN *, DBT *, DBT *, u_int32_t));
static int __ram_put __P((DB *, DB_TXN *, DBT *, DBT *, int)); 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_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_update __P((DB *, db_recno_t, int));
static int __ram_vmap __P((DB *, db_recno_t)); static int __ram_vmap __P((DB *, db_recno_t));
static int __ram_writeback __P((DB *)); 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. */ err: /* If we mmap'd a source file, discard it. */
if (rp->re_smap != NULL) 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 we opened a source file, discard it. */
if (rp->re_fd != -1) 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 * All cursors are queued from the master DB structure. Add the
* cursor to that queue. * cursor to that queue.
*/ */
DB_THREAD_LOCK(dbp); CURSOR_SETUP(dbp);
TAILQ_INSERT_HEAD(&dbp->curs_queue, dbc, links); TAILQ_INSERT_HEAD(&dbp->curs_queue, dbc, links);
DB_THREAD_UNLOCK(dbp); CURSOR_TEARDOWN(dbp);
*dbcp = dbc; *dbcp = dbc;
return (0); return (0);
@ -216,16 +215,10 @@ __ram_get(argdbp, txn, key, data, flags)
DB *argdbp; DB *argdbp;
DB_TXN *txn; DB_TXN *txn;
DBT *key, *data; DBT *key, *data;
int flags; u_int32_t flags;
{ {
BTREE *t;
DB *dbp; DB *dbp;
PAGE *h; int ret;
db_indx_t indx;
db_recno_t recno;
int exact, ret, stack;
stack = 0;
DEBUG_LWRITE(argdbp, txn, "ram_get", key, NULL, flags); DEBUG_LWRITE(argdbp, txn, "ram_get", key, NULL, flags);
@ -234,6 +227,30 @@ __ram_get(argdbp, txn, key, data, flags)
return (ret); return (ret);
GETHANDLE(argdbp, txn, &dbp, 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; t = dbp->internal;
/* Check the user's record number and fill in as necessary. */ /* Check the user's record number and fill in as necessary. */
@ -265,7 +282,6 @@ done: /* Discard the stack. */
if (stack) if (stack)
__bam_stkrel(dbp); __bam_stkrel(dbp);
PUTHANDLE(dbp);
return (ret); return (ret);
} }
@ -278,7 +294,7 @@ __ram_put(argdbp, txn, key, data, flags)
DB *argdbp; DB *argdbp;
DB_TXN *txn; DB_TXN *txn;
DBT *key, *data; DBT *key, *data;
int flags; u_int32_t flags;
{ {
BTREE *t; BTREE *t;
DB *dbp; DB *dbp;
@ -324,7 +340,7 @@ __ram_put(argdbp, txn, key, data, flags)
static int static int
__ram_sync(argdbp, flags) __ram_sync(argdbp, flags)
DB *argdbp; DB *argdbp;
int flags; u_int32_t flags;
{ {
DB *dbp; DB *dbp;
int ret; int ret;
@ -361,7 +377,7 @@ __ram_close(argdbp)
/* Close any underlying mmap region. */ /* Close any underlying mmap region. */
if (rp->re_smap != NULL) 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. */ /* Close any backing source file descriptor. */
if (rp->re_fd != -1) if (rp->re_fd != -1)
@ -403,17 +419,10 @@ __ram_c_iclose(dbp, dbc)
DB *dbp; DB *dbp;
DBC *dbc; 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. */ /* Remove the cursor from the queue. */
DB_THREAD_LOCK(dbp); CURSOR_SETUP(dbp);
TAILQ_REMOVE(&dbp->curs_queue, dbc, links); TAILQ_REMOVE(&dbp->curs_queue, dbc, links);
DB_THREAD_UNLOCK(dbp); CURSOR_TEARDOWN(dbp);
/* Discard the structures. */ /* Discard the structures. */
FREE(dbc->internal, sizeof(RCURSOR)); FREE(dbc->internal, sizeof(RCURSOR));
@ -429,7 +438,7 @@ __ram_c_iclose(dbp, dbc)
static int static int
__ram_c_del(dbc, flags) __ram_c_del(dbc, flags)
DBC *dbc; DBC *dbc;
int flags; u_int32_t flags;
{ {
DBT key; DBT key;
RCURSOR *cp; RCURSOR *cp;
@ -466,7 +475,7 @@ static int
__ram_c_get(dbc, key, data, flags) __ram_c_get(dbc, key, data, flags)
DBC *dbc; DBC *dbc;
DBT *key, *data; DBT *key, *data;
int flags; u_int32_t flags;
{ {
BTREE *t; BTREE *t;
DB *dbp; 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 * 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 && if (flags != DB_SET && flags != DB_SET_RANGE &&
(ret = __db_retcopy(key, &cp->recno, sizeof(cp->recno), (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. * 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 && if (ret == DB_KEYEMPTY &&
(flags == DB_NEXT || flags == DB_PREV)) (flags == DB_NEXT || flags == DB_PREV))
goto retry; goto retry;
@ -575,7 +584,7 @@ static int
__ram_c_put(dbc, key, data, flags) __ram_c_put(dbc, key, data, flags)
DBC *dbc; DBC *dbc;
DBT *key, *data; DBT *key, *data;
int flags; u_int32_t flags;
{ {
BTREE *t; BTREE *t;
RCURSOR *cp, copy; RCURSOR *cp, copy;
@ -624,28 +633,21 @@ split: arg = &cp->recno;
if ((ret = __bam_stkrel(dbp)) != 0) if ((ret = __bam_stkrel(dbp)) != 0)
goto err; goto err;
if (flags != DB_CURRENT) { switch (flags) {
/* Adjust the counts. */ case DB_AFTER:
if ((ret = __bam_adjust(dbp, t, 1)) != 0) /* Adjust the cursors. */
goto err; __ram_ca(dbp, cp->recno, CA_IAFTER);
switch (flags) { /* Set this cursor to reference the new record. */
case DB_AFTER: cp->recno = copy.recno + 1;
/* Adjust the cursors. */ break;
__ram_ca(dbp, cp->recno, CA_IAFTER); case DB_BEFORE:
/* Adjust the cursors. */
/* Set this cursor to reference the new record. */ __ram_ca(dbp, cp->recno, CA_IBEFORE);
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;
}
/* 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(). * Adjust the cursors. See the comment in __bam_ca_delete().
*/ */
DB_THREAD_LOCK(dbp); CURSOR_SETUP(dbp);
for (dbc = TAILQ_FIRST(&dbp->curs_queue); for (dbc = TAILQ_FIRST(&dbp->curs_queue);
dbc != NULL; dbc = TAILQ_NEXT(dbc, links)) { dbc != NULL; dbc = TAILQ_NEXT(dbc, links)) {
cp = (RCURSOR *)dbc->internal; cp = (RCURSOR *)dbc->internal;
@ -698,7 +700,7 @@ __ram_ca(dbp, recno, op)
break; break;
} }
} }
DB_THREAD_UNLOCK(dbp); CURSOR_TEARDOWN(dbp);
} }
#ifdef DEBUG #ifdef DEBUG
@ -715,14 +717,15 @@ __ram_cprint(dbp)
DBC *dbc; DBC *dbc;
RCURSOR *cp; RCURSOR *cp;
DB_THREAD_LOCK(dbp); CURSOR_SETUP(dbp);
for (dbc = TAILQ_FIRST(&dbp->curs_queue); for (dbc = TAILQ_FIRST(&dbp->curs_queue);
dbc != NULL; dbc = TAILQ_NEXT(dbc, links)) { dbc != NULL; dbc = TAILQ_NEXT(dbc, links)) {
cp = (RCURSOR *)dbc->internal; cp = (RCURSOR *)dbc->internal;
fprintf(stderr, fprintf(stderr,
"%#0x: recno: %lu\n", (u_int)cp, (u_long)cp->recno); "%#0x: recno: %lu\n", (u_int)cp, (u_long)cp->recno);
} }
DB_THREAD_UNLOCK(dbp); CURSOR_TEARDOWN(dbp);
return (0); return (0);
} }
#endif /* DEBUG */ #endif /* DEBUG */
@ -853,11 +856,11 @@ __ram_source(dbp, rp, fname)
const char *fname; const char *fname;
{ {
size_t size; size_t size;
u_int32_t mbytes, bytes; u_int32_t bytes, mbytes, oflags;
int oflags, ret; int ret;
if ((ret = __db_appname(dbp->dbenv, 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); return (ret);
oflags = F_ISSET(dbp, DB_AM_RDONLY) ? DB_RDONLY : 0; oflags = F_ISSET(dbp, DB_AM_RDONLY) ? DB_RDONLY : 0;
@ -886,7 +889,8 @@ __ram_source(dbp, rp, fname)
} }
size = mbytes * MEGABYTE + bytes; 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; goto err;
rp->re_cmap = rp->re_smap; rp->re_cmap = rp->re_smap;
rp->re_emap = (u_int8_t *)rp->re_smap + (rp->re_msize = size); rp->re_emap = (u_int8_t *)rp->re_smap + (rp->re_msize = size);
@ -952,7 +956,7 @@ __ram_writeback(dbp)
* open will fail. * open will fail.
*/ */
if (rp->re_smap != NULL) { 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; rp->re_smap = NULL;
} }
@ -1078,19 +1082,22 @@ __ram_fmap(dbp, top)
sp = (u_int8_t *)rp->re_cmap; sp = (u_int8_t *)rp->re_cmap;
ep = (u_int8_t *)rp->re_emap; ep = (u_int8_t *)rp->re_emap;
while (recno <= top) { while (recno < top) {
if (sp >= ep) { if (sp >= ep) {
F_SET(rp, RECNO_EOF); F_SET(rp, RECNO_EOF);
return (DB_NOTFOUND); return (DB_NOTFOUND);
} }
len = rp->re_len; len = rp->re_len;
for (p = t->bt_rdata.data; 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 * Another process may have read this record from the input
* file already, in which case we just want to discard the * file and stored it into the database already, in which
* new record. * 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 * XXX
* We should just do a seek, since the records are fixed * 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; sp = (u_int8_t *)rp->re_cmap;
ep = (u_int8_t *)rp->re_emap; ep = (u_int8_t *)rp->re_emap;
while (recno <= top) { while (recno < top) {
if (sp >= ep) { if (sp >= ep) {
F_SET(rp, RECNO_EOF); F_SET(rp, RECNO_EOF);
return (DB_NOTFOUND); 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 * Another process may have read this record from the input
* file already, in which case we just want to discard the * file and stored it into the database already, in which
* new record. * 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) { if (rp->re_last >= recno) {
data.size = sp - (u_int8_t *)data.data; data.size = sp - (u_int8_t *)data.data;
@ -1172,12 +1182,13 @@ __ram_add(dbp, recnop, data, flags, bi_flags)
DB *dbp; DB *dbp;
db_recno_t *recnop; db_recno_t *recnop;
DBT *data; DBT *data;
int flags, bi_flags; u_int32_t flags, bi_flags;
{ {
BKEYDATA *bk;
BTREE *t; BTREE *t;
PAGE *h; PAGE *h;
db_indx_t indx; db_indx_t indx;
int exact, ret, stack; int exact, isdeleted, ret, stack;
t = dbp->internal; t = dbp->internal;
@ -1190,34 +1201,63 @@ retry: /* Find the slot for insertion. */
stack = 1; stack = 1;
/* /*
* The recno access method doesn't currently support duplicates, so * If DB_NOOVERWRITE is set and the item already exists in the tree,
* if an identical key is already in the tree we're either overwriting * return an error unless the item has been marked for deletion.
* it or an error is returned.
*/ */
if (exact && LF_ISSET(DB_NOOVERWRITE)) { isdeleted = 0;
ret = DB_KEYEXIST; if (exact) {
goto err; 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 * 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 * 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 * new data item, replace the current item. If the key isn't an exact
* a new key/data pair, before the search location. * match, we're inserting a new key/data pair, before the search
* location.
*/ */
if ((ret = __bam_iitem(dbp, &h, &indx, NULL, switch (ret = __bam_iitem(dbp,
data, exact ? DB_CURRENT : DB_BEFORE, bi_flags)) == DB_NEEDSPLIT) { &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); (void)__bam_stkrel(dbp);
stack = 0; stack = 0;
if ((ret = __bam_split(dbp, recnop)) != 0)
goto err;
goto retry;
}
if (!exact && ret == 0) if ((ret = __bam_split(dbp, recnop)) != 0)
__bam_adjust(dbp, t, 1); break;
goto retry;
/* NOTREACHED */
default:
if (isdeleted)
__bam_ca_replace(dbp, h->pgno, indx, REPLACE_FAILED);
break;
}
err: if (stack) err: if (stack)
__bam_stkrel(dbp); __bam_stkrel(dbp);
return (ret); return (ret);
} }

View File

@ -1,7 +1,7 @@
/*- /*-
* See the file LICENSE for redistribution information. * See the file LICENSE for redistribution information.
* *
* Copyright (c) 1996, 1997 * Copyright (c) 1996, 1997, 1998
* Sleepycat Software. All rights reserved. * Sleepycat Software. All rights reserved.
*/ */
/* /*
@ -44,14 +44,11 @@
#include "config.h" #include "config.h"
#ifndef lint #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 */ #endif /* not lint */
#ifndef NO_SYSTEM_INCLUDES #ifndef NO_SYSTEM_INCLUDES
#include <sys/types.h> #include <sys/types.h>
#include <stdio.h>
#include <stdlib.h>
#endif #endif
#include "db_int.h" #include "db_int.h"
@ -62,13 +59,13 @@ static const char sccsid[] = "@(#)bt_rsearch.c 10.8 (Sleepycat) 8/24/97";
* __bam_rsearch -- * __bam_rsearch --
* Search a btree for a record number. * 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 int
__bam_rsearch(dbp, recnop, flags, stop, exactp) __bam_rsearch(dbp, recnop, flags, stop, exactp)
DB *dbp; DB *dbp;
db_recno_t *recnop; db_recno_t *recnop;
u_int flags; u_int32_t flags;
int stop, *exactp; int stop, *exactp;
{ {
BINTERNAL *bi; BINTERNAL *bi;
@ -78,7 +75,7 @@ __bam_rsearch(dbp, recnop, flags, stop, exactp)
RINTERNAL *ri; RINTERNAL *ri;
db_indx_t indx, top; db_indx_t indx, top;
db_pgno_t pg; db_pgno_t pg;
db_recno_t recno, total; db_recno_t i, recno, total;
int isappend, ret, stack; int isappend, ret, stack;
t = dbp->internal; t = dbp->internal;
@ -136,8 +133,7 @@ __bam_rsearch(dbp, recnop, flags, stop, exactp)
*exactp = 1; *exactp = 1;
else { else {
*exactp = 0; *exactp = 0;
if (flags == S_DELETE || if (!PAST_END_OK(flags) || recno > total + 1) {
flags == S_FIND || recno > total + 1) {
(void)memp_fput(dbp->mpf, h, 0); (void)memp_fput(dbp->mpf, h, 0);
(void)__BT_LPUT(dbp, lock); (void)__BT_LPUT(dbp, lock);
return (DB_NOTFOUND); return (DB_NOTFOUND);
@ -164,30 +160,65 @@ __bam_rsearch(dbp, recnop, flags, stop, exactp)
stack = 1; 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;;) { for (total = 0;;) {
switch (TYPE(h)) { switch (TYPE(h)) {
case P_LBTREE: 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); return (ret);
case P_IBTREE: case P_IBTREE:
for (indx = 0, top = NUM_ENT(h);;) { for (indx = 0, top = NUM_ENT(h);;) {
bi = GET_BINTERNAL(h, indx); bi = GET_BINTERNAL(h, indx);
if (++indx == top || total + bi->nrecs > recno) if (++indx == top || total + bi->nrecs >= recno)
break; break;
total += bi->nrecs; total += bi->nrecs;
} }
pg = bi->pgno; pg = bi->pgno;
break; break;
case P_LRECNO: 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); return (ret);
case P_IRECNO: case P_IRECNO:
for (indx = 0, top = NUM_ENT(h);;) { for (indx = 0, top = NUM_ENT(h);;) {
ri = GET_RINTERNAL(h, indx); ri = GET_RINTERNAL(h, indx);
if (++indx == top || total + ri->nrecs > recno) if (++indx == top || total + ri->nrecs >= recno)
break; break;
total += ri->nrecs; total += ri->nrecs;
} }
@ -244,13 +275,13 @@ err: BT_STK_POP(t);
* __bam_adjust -- * __bam_adjust --
* Adjust the tree after adding or deleting a record. * 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 int
__bam_adjust(dbp, t, adjust) __bam_adjust(dbp, t, adjust)
DB *dbp; DB *dbp;
BTREE *t; BTREE *t;
int adjust; int32_t adjust;
{ {
EPG *epg; EPG *epg;
PAGE *h; PAGE *h;
@ -264,7 +295,7 @@ __bam_adjust(dbp, t, adjust)
(ret = __bam_cadjust_log(dbp->dbenv->lg_info, (ret = __bam_cadjust_log(dbp->dbenv->lg_info,
dbp->txn, &LSN(h), 0, dbp->log_fileid, dbp->txn, &LSN(h), 0, dbp->log_fileid,
PGNO(h), &LSN(h), (u_int32_t)epg->indx, PGNO(h), &LSN(h), (u_int32_t)epg->indx,
(int32_t)adjust, 1)) != 0) adjust, 1)) != 0)
return (ret); return (ret);
if (TYPE(h) == P_IBTREE) if (TYPE(h) == P_IBTREE)
@ -322,26 +353,31 @@ db_recno_t
__bam_total(h) __bam_total(h)
PAGE *h; PAGE *h;
{ {
db_recno_t recs; db_recno_t nrecs;
db_indx_t nxt, top; db_indx_t indx, top;
nrecs = 0;
top = NUM_ENT(h);
switch (TYPE(h)) { switch (TYPE(h)) {
case P_LBTREE: 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; break;
case P_IBTREE: case P_IBTREE:
for (recs = 0, nxt = 0, top = NUM_ENT(h); nxt < top; ++nxt) for (indx = 0; indx < top; indx += O_INDX)
recs += GET_BINTERNAL(h, nxt)->nrecs; nrecs += GET_BINTERNAL(h, indx)->nrecs;
break; break;
case P_LRECNO: case P_LRECNO:
recs = NUM_ENT(h); nrecs = NUM_ENT(h);
break; break;
case P_IRECNO: case P_IRECNO:
for (recs = 0, nxt = 0, top = NUM_ENT(h); nxt < top; ++nxt) for (indx = 0; indx < top; indx += O_INDX)
recs += GET_RINTERNAL(h, nxt)->nrecs; nrecs += GET_RINTERNAL(h, indx)->nrecs;
break; break;
default:
abort();
} }
return (recs);
return (nrecs);
} }

View File

@ -1,7 +1,7 @@
/*- /*-
* See the file LICENSE for redistribution information. * See the file LICENSE for redistribution information.
* *
* Copyright (c) 1996, 1997 * Copyright (c) 1996, 1997, 1998
* Sleepycat Software. All rights reserved. * Sleepycat Software. All rights reserved.
*/ */
/* /*
@ -47,15 +47,13 @@
#include "config.h" #include "config.h"
#ifndef lint #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 */ #endif /* not lint */
#ifndef NO_SYSTEM_INCLUDES #ifndef NO_SYSTEM_INCLUDES
#include <sys/types.h> #include <sys/types.h>
#include <errno.h> #include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h> #include <string.h>
#endif #endif
@ -68,13 +66,13 @@ static const char sccsid[] = "@(#)bt_search.c 10.9 (Sleepycat) 11/18/97";
* Search a btree for a key. * Search a btree for a key.
* *
* PUBLIC: int __bam_search __P((DB *, * 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 int
__bam_search(dbp, key, flags, stop, recnop, exactp) __bam_search(dbp, key, flags, stop, recnop, exactp)
DB *dbp; DB *dbp;
const DBT *key; const DBT *key;
u_int flags; u_int32_t flags;
int stop, *exactp; int stop, *exactp;
db_recno_t *recnop; db_recno_t *recnop;
{ {
@ -109,8 +107,7 @@ __bam_search(dbp, key, flags, stop, recnop, exactp)
* Retrieve the root page. * Retrieve the root page.
*/ */
pg = PGNO_ROOT; pg = PGNO_ROOT;
stack = F_ISSET(dbp, DB_BT_RECNUM) && stack = F_ISSET(dbp, DB_BT_RECNUM) && LF_ISSET(S_STACK);
(flags == S_INSERT || flags == S_DELETE);
if ((ret = __bam_lget(dbp, if ((ret = __bam_lget(dbp,
0, pg, stack ? DB_LOCK_WRITE : DB_LOCK_READ, &lock)) != 0) 0, pg, stack ? DB_LOCK_WRITE : DB_LOCK_READ, &lock)) != 0)
return (ret); return (ret);
@ -179,6 +176,14 @@ __bam_search(dbp, key, flags, stop, recnop, exactp)
if (LF_ISSET(S_EXACT)) if (LF_ISSET(S_EXACT))
goto notfound; 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); BT_STK_ENTER(t, h, base, lock, ret);
return (ret); return (ret);
} }
@ -249,7 +254,10 @@ match: *exactp = 1;
/* /*
* If we got here, we know that we have a btree leaf page. * 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)) if (LF_ISSET(S_DUPLAST))
while (indx < (db_indx_t)(NUM_ENT(h) - P_INDX) && while (indx < (db_indx_t)(NUM_ENT(h) - P_INDX) &&
@ -261,8 +269,8 @@ match: *exactp = 1;
indx -= P_INDX; indx -= P_INDX;
/* /*
* Now check if we are allowed to return deleted item; if not * Now check if we are allowed to return deleted items; if not
* find/last the first non-deleted item. * find the next (or previous) non-deleted item.
*/ */
if (LF_ISSET(S_DELNO)) { if (LF_ISSET(S_DELNO)) {
if (LF_ISSET(S_DUPLAST)) if (LF_ISSET(S_DUPLAST))

View File

@ -1,7 +1,7 @@
/*- /*-
* See the file LICENSE for redistribution information. * See the file LICENSE for redistribution information.
* *
* Copyright (c) 1996, 1997 * Copyright (c) 1996, 1997, 1998
* Sleepycat Software. All rights reserved. * Sleepycat Software. All rights reserved.
*/ */
/* /*
@ -44,7 +44,7 @@
#include "config.h" #include "config.h"
#ifndef lint #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 */ #endif /* not lint */
#ifndef NO_SYSTEM_INCLUDES #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 <errno.h>
#include <limits.h> #include <limits.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h> #include <string.h>
#endif #endif
@ -168,8 +166,10 @@ __bam_root(dbp, cp)
t = dbp->internal; t = dbp->internal;
/* Yeah, right. */ /* Yeah, right. */
if (cp->page->level >= MAXBTREELEVEL) if (cp->page->level >= MAXBTREELEVEL) {
return (ENOSPC); ret = ENOSPC;
goto err;
}
/* Create new left and right pages for the split. */ /* Create new left and right pages for the split. */
lp = rp = NULL; lp = rp = NULL;
@ -237,18 +237,16 @@ __bam_page(dbp, pp, cp)
DB *dbp; DB *dbp;
EPG *pp, *cp; EPG *pp, *cp;
{ {
BTREE *t;
DB_LOCK tplock; DB_LOCK tplock;
PAGE *lp, *rp, *tp; PAGE *lp, *rp, *tp;
int ret; int ret;
t = dbp->internal;
lp = rp = tp = NULL; lp = rp = tp = NULL;
ret = -1; ret = -1;
/* Create new right page for the split. */ /* Create new right page for the split. */
if ((ret = __bam_new(dbp, TYPE(cp->page), &rp)) != 0) if ((ret = __bam_new(dbp, TYPE(cp->page), &rp)) != 0)
return (ret); goto err;
P_INIT(rp, dbp->pgsize, rp->pgno, P_INIT(rp, dbp->pgsize, rp->pgno,
ISINTERNAL(cp->page) ? PGNO_INVALID : cp->page->pgno, ISINTERNAL(cp->page) ? PGNO_INVALID : cp->page->pgno,
ISINTERNAL(cp->page) ? PGNO_INVALID : cp->page->next_pgno, ISINTERNAL(cp->page) ? PGNO_INVALID : cp->page->next_pgno,
@ -259,7 +257,7 @@ __bam_page(dbp, pp, cp)
ret = ENOMEM; ret = ENOMEM;
goto err; goto err;
} }
#ifdef DEBUG #ifdef DIAGNOSTIC
memset(lp, 0xff, dbp->pgsize); memset(lp, 0xff, dbp->pgsize);
#endif #endif
P_INIT(lp, dbp->pgsize, cp->page->pgno, P_INIT(lp, dbp->pgsize, cp->page->pgno,
@ -906,13 +904,13 @@ __bam_copy(dbp, pp, cp, nxt, stop)
PAGE *pp, *cp; PAGE *pp, *cp;
u_int32_t nxt, stop; 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 * Copy the rest of the data to the right page. Nxt is the next
* offset placed on the target page. * 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)) { switch (TYPE(pp)) {
case P_IBTREE: case P_IBTREE:
if (B_TYPE(GET_BINTERNAL(pp, nxt)->type) == B_KEYDATA) if (B_TYPE(GET_BINTERNAL(pp, nxt)->type) == B_KEYDATA)

View File

@ -1,21 +1,20 @@
/*- /*-
* See the file LICENSE for redistribution information. * See the file LICENSE for redistribution information.
* *
* Copyright (c) 1996, 1997 * Copyright (c) 1996, 1997, 1998
* Sleepycat Software. All rights reserved. * Sleepycat Software. All rights reserved.
*/ */
#include "config.h" #include "config.h"
#ifndef lint #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 */ #endif /* not lint */
#ifndef NO_SYSTEM_INCLUDES #ifndef NO_SYSTEM_INCLUDES
#include <sys/types.h> #include <sys/types.h>
#include <errno.h> #include <errno.h>
#include <stdlib.h>
#include <string.h> #include <string.h>
#endif #endif
@ -29,14 +28,14 @@ static void __bam_add_rstat __P((DB_BTREE_LSTAT *, DB_BTREE_STAT *));
* __bam_stat -- * __bam_stat --
* Gather/print the btree statistics * 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 int
__bam_stat(argdbp, spp, db_malloc, flags) __bam_stat(argdbp, spp, db_malloc, flags)
DB *argdbp; DB *argdbp;
void *spp; void *spp;
void *(*db_malloc) __P((size_t)); void *(*db_malloc) __P((size_t));
int flags; u_int32_t flags;
{ {
BTMETA *meta; BTMETA *meta;
BTREE *t; BTREE *t;

View File

@ -1,16 +1,12 @@
/*- /*-
* See the file LICENSE for redistribution information. * See the file LICENSE for redistribution information.
* *
* Copyright (c) 1996, 1997 * Copyright (c) 1996, 1997, 1998
* Sleepycat Software. All rights reserved. * 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 PREFIX bam
/* /*

View File

@ -15,8 +15,6 @@
#include "db_dispatch.h" #include "db_dispatch.h"
#include "btree.h" #include "btree.h"
#include "db_am.h" #include "db_am.h"
#include "common_ext.h"
/* /*
* PUBLIC: int __bam_pg_alloc_log * PUBLIC: int __bam_pg_alloc_log
* PUBLIC: __P((DB_LOG *, DB_TXN *, DB_LSN *, u_int32_t, * 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); bp += sizeof(ptype);
memcpy(bp, &next, sizeof(next)); memcpy(bp, &next, sizeof(next));
bp += sizeof(next); bp += sizeof(next);
#ifdef DEBUG #ifdef DIAGNOSTIC
if ((u_int32_t)(bp - (u_int8_t *)logrec.data) != logrec.size) if ((u_int32_t)(bp - (u_int8_t *)logrec.data) != logrec.size)
fprintf(stderr, "Error in log record length"); fprintf(stderr, "Error in log record length");
#endif #endif
@ -101,22 +99,23 @@ int __bam_pg_alloc_log(logp, txnid, ret_lsnp, flags,
* PUBLIC: __P((DB_LOG *, DBT *, DB_LSN *, int, void *)); * PUBLIC: __P((DB_LOG *, DBT *, DB_LSN *, int, void *));
*/ */
int int
__bam_pg_alloc_print(notused1, dbtp, lsnp, notused3, notused4) __bam_pg_alloc_print(notused1, dbtp, lsnp, notused2, notused3)
DB_LOG *notused1; DB_LOG *notused1;
DBT *dbtp; DBT *dbtp;
DB_LSN *lsnp; DB_LSN *lsnp;
int notused3; int notused2;
void *notused4; void *notused3;
{ {
__bam_pg_alloc_args *argp; __bam_pg_alloc_args *argp;
u_int32_t i; u_int32_t i;
int c, ret; u_int ch;
int ret;
i = 0; i = 0;
c = 0; ch = 0;
notused1 = NULL; notused1 = NULL;
notused3 = 0; notused2 = 0;
notused4 = NULL; notused3 = NULL;
if ((ret = __bam_pg_alloc_read(dbtp->data, &argp)) != 0) if ((ret = __bam_pg_alloc_read(dbtp->data, &argp)) != 0)
return (ret); return (ret);
@ -249,7 +248,7 @@ int __bam_pg_free_log(logp, txnid, ret_lsnp, flags,
} }
memcpy(bp, &next, sizeof(next)); memcpy(bp, &next, sizeof(next));
bp += sizeof(next); bp += sizeof(next);
#ifdef DEBUG #ifdef DIAGNOSTIC
if ((u_int32_t)(bp - (u_int8_t *)logrec.data) != logrec.size) if ((u_int32_t)(bp - (u_int8_t *)logrec.data) != logrec.size)
fprintf(stderr, "Error in log record length"); fprintf(stderr, "Error in log record length");
#endif #endif
@ -265,22 +264,23 @@ int __bam_pg_free_log(logp, txnid, ret_lsnp, flags,
* PUBLIC: __P((DB_LOG *, DBT *, DB_LSN *, int, void *)); * PUBLIC: __P((DB_LOG *, DBT *, DB_LSN *, int, void *));
*/ */
int int
__bam_pg_free_print(notused1, dbtp, lsnp, notused3, notused4) __bam_pg_free_print(notused1, dbtp, lsnp, notused2, notused3)
DB_LOG *notused1; DB_LOG *notused1;
DBT *dbtp; DBT *dbtp;
DB_LSN *lsnp; DB_LSN *lsnp;
int notused3; int notused2;
void *notused4; void *notused3;
{ {
__bam_pg_free_args *argp; __bam_pg_free_args *argp;
u_int32_t i; u_int32_t i;
int c, ret; u_int ch;
int ret;
i = 0; i = 0;
c = 0; ch = 0;
notused1 = NULL; notused1 = NULL;
notused3 = 0; notused2 = 0;
notused4 = NULL; notused3 = NULL;
if ((ret = __bam_pg_free_read(dbtp->data, &argp)) != 0) if ((ret = __bam_pg_free_read(dbtp->data, &argp)) != 0)
return (ret); 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); (u_long)argp->meta_lsn.file, (u_long)argp->meta_lsn.offset);
printf("\theader: "); printf("\theader: ");
for (i = 0; i < argp->header.size; i++) { for (i = 0; i < argp->header.size; i++) {
c = ((char *)argp->header.data)[i]; ch = ((u_int8_t *)argp->header.data)[i];
if (isprint(c) || c == 0xa) if (isprint(ch) || ch == 0xa)
putchar(c); putchar(ch);
else else
printf("%#x ", c); printf("%#x ", ch);
} }
printf("\n"); printf("\n");
printf("\tnext: %lu\n", (u_long)argp->next); 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); memcpy(bp, pg->data, pg->size);
bp += pg->size; bp += pg->size;
} }
#ifdef DEBUG #ifdef DIAGNOSTIC
if ((u_int32_t)(bp - (u_int8_t *)logrec.data) != logrec.size) if ((u_int32_t)(bp - (u_int8_t *)logrec.data) != logrec.size)
fprintf(stderr, "Error in log record length"); fprintf(stderr, "Error in log record length");
#endif #endif
@ -459,22 +459,23 @@ int __bam_split_log(logp, txnid, ret_lsnp, flags,
* PUBLIC: __P((DB_LOG *, DBT *, DB_LSN *, int, void *)); * PUBLIC: __P((DB_LOG *, DBT *, DB_LSN *, int, void *));
*/ */
int int
__bam_split_print(notused1, dbtp, lsnp, notused3, notused4) __bam_split_print(notused1, dbtp, lsnp, notused2, notused3)
DB_LOG *notused1; DB_LOG *notused1;
DBT *dbtp; DBT *dbtp;
DB_LSN *lsnp; DB_LSN *lsnp;
int notused3; int notused2;
void *notused4; void *notused3;
{ {
__bam_split_args *argp; __bam_split_args *argp;
u_int32_t i; u_int32_t i;
int c, ret; u_int ch;
int ret;
i = 0; i = 0;
c = 0; ch = 0;
notused1 = NULL; notused1 = NULL;
notused3 = 0; notused2 = 0;
notused4 = NULL; notused3 = NULL;
if ((ret = __bam_split_read(dbtp->data, &argp)) != 0) if ((ret = __bam_split_read(dbtp->data, &argp)) != 0)
return (ret); return (ret);
@ -498,11 +499,11 @@ __bam_split_print(notused1, dbtp, lsnp, notused3, notused4)
(u_long)argp->nlsn.file, (u_long)argp->nlsn.offset); (u_long)argp->nlsn.file, (u_long)argp->nlsn.offset);
printf("\tpg: "); printf("\tpg: ");
for (i = 0; i < argp->pg.size; i++) { for (i = 0; i < argp->pg.size; i++) {
c = ((char *)argp->pg.data)[i]; ch = ((u_int8_t *)argp->pg.data)[i];
if (isprint(c) || c == 0xa) if (isprint(ch) || ch == 0xa)
putchar(c); putchar(ch);
else else
printf("%#x ", c); printf("%#x ", ch);
} }
printf("\n"); printf("\n");
printf("\n"); printf("\n");
@ -639,7 +640,7 @@ int __bam_rsplit_log(logp, txnid, ret_lsnp, flags,
else else
memset(bp, 0, sizeof(*rootlsn)); memset(bp, 0, sizeof(*rootlsn));
bp += sizeof(*rootlsn); bp += sizeof(*rootlsn);
#ifdef DEBUG #ifdef DIAGNOSTIC
if ((u_int32_t)(bp - (u_int8_t *)logrec.data) != logrec.size) if ((u_int32_t)(bp - (u_int8_t *)logrec.data) != logrec.size)
fprintf(stderr, "Error in log record length"); fprintf(stderr, "Error in log record length");
#endif #endif
@ -655,22 +656,23 @@ int __bam_rsplit_log(logp, txnid, ret_lsnp, flags,
* PUBLIC: __P((DB_LOG *, DBT *, DB_LSN *, int, void *)); * PUBLIC: __P((DB_LOG *, DBT *, DB_LSN *, int, void *));
*/ */
int int
__bam_rsplit_print(notused1, dbtp, lsnp, notused3, notused4) __bam_rsplit_print(notused1, dbtp, lsnp, notused2, notused3)
DB_LOG *notused1; DB_LOG *notused1;
DBT *dbtp; DBT *dbtp;
DB_LSN *lsnp; DB_LSN *lsnp;
int notused3; int notused2;
void *notused4; void *notused3;
{ {
__bam_rsplit_args *argp; __bam_rsplit_args *argp;
u_int32_t i; u_int32_t i;
int c, ret; u_int ch;
int ret;
i = 0; i = 0;
c = 0; ch = 0;
notused1 = NULL; notused1 = NULL;
notused3 = 0; notused2 = 0;
notused4 = NULL; notused3 = NULL;
if ((ret = __bam_rsplit_read(dbtp->data, &argp)) != 0) if ((ret = __bam_rsplit_read(dbtp->data, &argp)) != 0)
return (ret); return (ret);
@ -685,21 +687,21 @@ __bam_rsplit_print(notused1, dbtp, lsnp, notused3, notused4)
printf("\tpgno: %lu\n", (u_long)argp->pgno); printf("\tpgno: %lu\n", (u_long)argp->pgno);
printf("\tpgdbt: "); printf("\tpgdbt: ");
for (i = 0; i < argp->pgdbt.size; i++) { for (i = 0; i < argp->pgdbt.size; i++) {
c = ((char *)argp->pgdbt.data)[i]; ch = ((u_int8_t *)argp->pgdbt.data)[i];
if (isprint(c) || c == 0xa) if (isprint(ch) || ch == 0xa)
putchar(c); putchar(ch);
else else
printf("%#x ", c); printf("%#x ", ch);
} }
printf("\n"); printf("\n");
printf("\tnrec: %lu\n", (u_long)argp->nrec); printf("\tnrec: %lu\n", (u_long)argp->nrec);
printf("\trootent: "); printf("\trootent: ");
for (i = 0; i < argp->rootent.size; i++) { for (i = 0; i < argp->rootent.size; i++) {
c = ((char *)argp->rootent.data)[i]; ch = ((u_int8_t *)argp->rootent.data)[i];
if (isprint(c) || c == 0xa) if (isprint(ch) || ch == 0xa)
putchar(c); putchar(ch);
else else
printf("%#x ", c); printf("%#x ", ch);
} }
printf("\n"); printf("\n");
printf("\trootlsn: [%lu][%lu]\n", printf("\trootlsn: [%lu][%lu]\n",
@ -817,7 +819,7 @@ int __bam_adj_log(logp, txnid, ret_lsnp, flags,
bp += sizeof(indx_copy); bp += sizeof(indx_copy);
memcpy(bp, &is_insert, sizeof(is_insert)); memcpy(bp, &is_insert, sizeof(is_insert));
bp += sizeof(is_insert); bp += sizeof(is_insert);
#ifdef DEBUG #ifdef DIAGNOSTIC
if ((u_int32_t)(bp - (u_int8_t *)logrec.data) != logrec.size) if ((u_int32_t)(bp - (u_int8_t *)logrec.data) != logrec.size)
fprintf(stderr, "Error in log record length"); fprintf(stderr, "Error in log record length");
#endif #endif
@ -833,22 +835,23 @@ int __bam_adj_log(logp, txnid, ret_lsnp, flags,
* PUBLIC: __P((DB_LOG *, DBT *, DB_LSN *, int, void *)); * PUBLIC: __P((DB_LOG *, DBT *, DB_LSN *, int, void *));
*/ */
int int
__bam_adj_print(notused1, dbtp, lsnp, notused3, notused4) __bam_adj_print(notused1, dbtp, lsnp, notused2, notused3)
DB_LOG *notused1; DB_LOG *notused1;
DBT *dbtp; DBT *dbtp;
DB_LSN *lsnp; DB_LSN *lsnp;
int notused3; int notused2;
void *notused4; void *notused3;
{ {
__bam_adj_args *argp; __bam_adj_args *argp;
u_int32_t i; u_int32_t i;
int c, ret; u_int ch;
int ret;
i = 0; i = 0;
c = 0; ch = 0;
notused1 = NULL; notused1 = NULL;
notused3 = 0; notused2 = 0;
notused4 = NULL; notused3 = NULL;
if ((ret = __bam_adj_read(dbtp->data, &argp)) != 0) if ((ret = __bam_adj_read(dbtp->data, &argp)) != 0)
return (ret); return (ret);
@ -975,7 +978,7 @@ int __bam_cadjust_log(logp, txnid, ret_lsnp, flags,
bp += sizeof(adjust); bp += sizeof(adjust);
memcpy(bp, &total, sizeof(total)); memcpy(bp, &total, sizeof(total));
bp += sizeof(total); bp += sizeof(total);
#ifdef DEBUG #ifdef DIAGNOSTIC
if ((u_int32_t)(bp - (u_int8_t *)logrec.data) != logrec.size) if ((u_int32_t)(bp - (u_int8_t *)logrec.data) != logrec.size)
fprintf(stderr, "Error in log record length"); fprintf(stderr, "Error in log record length");
#endif #endif
@ -991,22 +994,23 @@ int __bam_cadjust_log(logp, txnid, ret_lsnp, flags,
* PUBLIC: __P((DB_LOG *, DBT *, DB_LSN *, int, void *)); * PUBLIC: __P((DB_LOG *, DBT *, DB_LSN *, int, void *));
*/ */
int int
__bam_cadjust_print(notused1, dbtp, lsnp, notused3, notused4) __bam_cadjust_print(notused1, dbtp, lsnp, notused2, notused3)
DB_LOG *notused1; DB_LOG *notused1;
DBT *dbtp; DBT *dbtp;
DB_LSN *lsnp; DB_LSN *lsnp;
int notused3; int notused2;
void *notused4; void *notused3;
{ {
__bam_cadjust_args *argp; __bam_cadjust_args *argp;
u_int32_t i; u_int32_t i;
int c, ret; u_int ch;
int ret;
i = 0; i = 0;
c = 0; ch = 0;
notused1 = NULL; notused1 = NULL;
notused3 = 0; notused2 = 0;
notused4 = NULL; notused3 = NULL;
if ((ret = __bam_cadjust_read(dbtp->data, &argp)) != 0) if ((ret = __bam_cadjust_read(dbtp->data, &argp)) != 0)
return (ret); return (ret);
@ -1124,7 +1128,7 @@ int __bam_cdel_log(logp, txnid, ret_lsnp, flags,
bp += sizeof(*lsn); bp += sizeof(*lsn);
memcpy(bp, &indx, sizeof(indx)); memcpy(bp, &indx, sizeof(indx));
bp += sizeof(indx); bp += sizeof(indx);
#ifdef DEBUG #ifdef DIAGNOSTIC
if ((u_int32_t)(bp - (u_int8_t *)logrec.data) != logrec.size) if ((u_int32_t)(bp - (u_int8_t *)logrec.data) != logrec.size)
fprintf(stderr, "Error in log record length"); fprintf(stderr, "Error in log record length");
#endif #endif
@ -1140,22 +1144,23 @@ int __bam_cdel_log(logp, txnid, ret_lsnp, flags,
* PUBLIC: __P((DB_LOG *, DBT *, DB_LSN *, int, void *)); * PUBLIC: __P((DB_LOG *, DBT *, DB_LSN *, int, void *));
*/ */
int int
__bam_cdel_print(notused1, dbtp, lsnp, notused3, notused4) __bam_cdel_print(notused1, dbtp, lsnp, notused2, notused3)
DB_LOG *notused1; DB_LOG *notused1;
DBT *dbtp; DBT *dbtp;
DB_LSN *lsnp; DB_LSN *lsnp;
int notused3; int notused2;
void *notused4; void *notused3;
{ {
__bam_cdel_args *argp; __bam_cdel_args *argp;
u_int32_t i; u_int32_t i;
int c, ret; u_int ch;
int ret;
i = 0; i = 0;
c = 0; ch = 0;
notused1 = NULL; notused1 = NULL;
notused3 = 0; notused2 = 0;
notused4 = NULL; notused3 = NULL;
if ((ret = __bam_cdel_read(dbtp->data, &argp)) != 0) if ((ret = __bam_cdel_read(dbtp->data, &argp)) != 0)
return (ret); return (ret);
@ -1307,7 +1312,7 @@ int __bam_repl_log(logp, txnid, ret_lsnp, flags,
bp += sizeof(prefix); bp += sizeof(prefix);
memcpy(bp, &suffix, sizeof(suffix)); memcpy(bp, &suffix, sizeof(suffix));
bp += sizeof(suffix); bp += sizeof(suffix);
#ifdef DEBUG #ifdef DIAGNOSTIC
if ((u_int32_t)(bp - (u_int8_t *)logrec.data) != logrec.size) if ((u_int32_t)(bp - (u_int8_t *)logrec.data) != logrec.size)
fprintf(stderr, "Error in log record length"); fprintf(stderr, "Error in log record length");
#endif #endif
@ -1323,22 +1328,23 @@ int __bam_repl_log(logp, txnid, ret_lsnp, flags,
* PUBLIC: __P((DB_LOG *, DBT *, DB_LSN *, int, void *)); * PUBLIC: __P((DB_LOG *, DBT *, DB_LSN *, int, void *));
*/ */
int int
__bam_repl_print(notused1, dbtp, lsnp, notused3, notused4) __bam_repl_print(notused1, dbtp, lsnp, notused2, notused3)
DB_LOG *notused1; DB_LOG *notused1;
DBT *dbtp; DBT *dbtp;
DB_LSN *lsnp; DB_LSN *lsnp;
int notused3; int notused2;
void *notused4; void *notused3;
{ {
__bam_repl_args *argp; __bam_repl_args *argp;
u_int32_t i; u_int32_t i;
int c, ret; u_int ch;
int ret;
i = 0; i = 0;
c = 0; ch = 0;
notused1 = NULL; notused1 = NULL;
notused3 = 0; notused2 = 0;
notused4 = NULL; notused3 = NULL;
if ((ret = __bam_repl_read(dbtp->data, &argp)) != 0) if ((ret = __bam_repl_read(dbtp->data, &argp)) != 0)
return (ret); return (ret);
@ -1357,20 +1363,20 @@ __bam_repl_print(notused1, dbtp, lsnp, notused3, notused4)
printf("\tisdeleted: %lu\n", (u_long)argp->isdeleted); printf("\tisdeleted: %lu\n", (u_long)argp->isdeleted);
printf("\torig: "); printf("\torig: ");
for (i = 0; i < argp->orig.size; i++) { for (i = 0; i < argp->orig.size; i++) {
c = ((char *)argp->orig.data)[i]; ch = ((u_int8_t *)argp->orig.data)[i];
if (isprint(c) || c == 0xa) if (isprint(ch) || ch == 0xa)
putchar(c); putchar(ch);
else else
printf("%#x ", c); printf("%#x ", ch);
} }
printf("\n"); printf("\n");
printf("\trepl: "); printf("\trepl: ");
for (i = 0; i < argp->repl.size; i++) { for (i = 0; i < argp->repl.size; i++) {
c = ((char *)argp->repl.data)[i]; ch = ((u_int8_t *)argp->repl.data)[i];
if (isprint(c) || c == 0xa) if (isprint(ch) || ch == 0xa)
putchar(c); putchar(ch);
else else
printf("%#x ", c); printf("%#x ", ch);
} }
printf("\n"); printf("\n");
printf("\tprefix: %lu\n", (u_long)argp->prefix); printf("\tprefix: %lu\n", (u_long)argp->prefix);

View File

@ -1,14 +1,14 @@
/*- /*-
* See the file LICENSE for redistribution information. * See the file LICENSE for redistribution information.
* *
* Copyright (c) 1996, 1997 * Copyright (c) 1996, 1997, 1998
* Sleepycat Software. All rights reserved. * Sleepycat Software. All rights reserved.
*/ */
#include "config.h" #include "config.h"
#ifndef lint #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 */ #endif /* not lint */
#ifndef NO_SYSTEM_INCLUDES #ifndef NO_SYSTEM_INCLUDES

View File

@ -1,23 +1,21 @@
/*- /*-
* See the file LICENSE for redistribution information. * See the file LICENSE for redistribution information.
* *
* Copyright (c) 1996, 1997 * Copyright (c) 1996, 1997, 1998
* Sleepycat Software. All rights reserved. * Sleepycat Software. All rights reserved.
*/ */
#include "config.h" #include "config.h"
#ifndef lint #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 */ #endif /* not lint */
#ifndef NO_SYSTEM_INCLUDES #ifndef NO_SYSTEM_INCLUDES
#include <sys/param.h> #include <sys/types.h>
#include <sys/stat.h>
#include <ctype.h> #include <ctype.h>
#include <errno.h> #include <errno.h>
#include <fcntl.h>
#include <signal.h> #include <signal.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.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 "clib_ext.h"
#include "common_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_parse __P((DB_ENV *, char *));
static int __db_tmp_dir __P((DB_ENV *, int)); static int __db_tmp_dir __P((DB_ENV *, u_int32_t));
static int __db_tmp_open __P((DB_ENV *, char *, int *)); static int __db_tmp_open __P((DB_ENV *, u_int32_t, char *, int *));
/* /*
* db_version -- * db_version --
* Return verision information. * Return version information.
*/ */
char * char *
db_version(majverp, minverp, patchp) db_version(majverp, minverp, patchp)
@ -65,16 +63,18 @@ db_appinit(db_home, db_config, dbenv, flags)
const char *db_home; const char *db_home;
char * const *db_config; char * const *db_config;
DB_ENV *dbenv; DB_ENV *dbenv;
int flags; u_int32_t flags;
{ {
FILE *fp; FILE *fp;
int ret; int mode, ret;
char * const *p; char * const *p;
char *lp, buf[MAXPATHLEN * 2]; char *lp, buf[MAXPATHLEN * 2];
/* Validate arguments. */ /* Validate arguments. */
if (dbenv == NULL) if (dbenv == NULL)
return (EINVAL); return (EINVAL);
#ifdef HAVE_SPINLOCKS #ifdef HAVE_SPINLOCKS
#define OKFLAGS \ #define OKFLAGS \
(DB_CREATE | DB_NOMMAP | DB_THREAD | DB_INIT_LOCK | DB_INIT_LOG | \ (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) if ((ret = __db_fchk(dbenv, "db_appinit", flags, OKFLAGS)) != 0)
return (ret); return (ret);
#define RECOVERY_FLAGS (DB_CREATE | DB_INIT_TXN | DB_INIT_LOG) /* Transactions imply logging. */
if (LF_ISSET(DB_RECOVER | DB_RECOVER_FATAL) && if (LF_ISSET(DB_INIT_TXN))
LF_ISSET(RECOVERY_FLAGS) != RECOVERY_FLAGS) LF_SET(DB_INIT_LOG);
return (__db_ferr(dbenv, "db_appinit", 1));
/* Convert the db_appinit(3) flags. */ /* Convert the db_appinit(3) flags. */
if (LF_ISSET(DB_THREAD)) if (LF_ISSET(DB_THREAD))
@ -147,47 +146,48 @@ db_appinit(db_home, db_config, dbenv, flags)
F_SET(dbenv, DB_ENV_APPINIT); 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)) { if (LF_ISSET(DB_RECOVER | DB_RECOVER_FATAL)) {
/* Remove all the old shared memory regions. */ if ((ret = log_unlink(NULL, 1, dbenv)) != 0)
if ((ret = log_unlink(NULL, 1 /* force */, dbenv)) != 0)
goto err; goto err;
if ((ret = memp_unlink(NULL, 1 /* force */, dbenv)) != 0) if ((ret = memp_unlink(NULL, 1, dbenv)) != 0)
goto err; goto err;
if ((ret = lock_unlink(NULL, 1 /* force */, dbenv)) != 0) if ((ret = lock_unlink(NULL, 1, dbenv)) != 0)
goto err; goto err;
if ((ret = txn_unlink(NULL, 1 /* force */, dbenv)) != 0) if ((ret = txn_unlink(NULL, 1, dbenv)) != 0)
goto err; goto err;
} }
/* Transactions imply logging. */ /*
if (LF_ISSET(DB_INIT_TXN)) * Create the new shared regions.
LF_SET(DB_INIT_LOG); *
* Default permissions are read-write for both owner and group.
/* Default permissions are 0660. */ */
#undef DB_DEFPERM mode = __db_omode("rwrw--");
#define DB_DEFPERM (S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP)
/* Initialize the subsystems. */
if (LF_ISSET(DB_INIT_LOCK) && (ret = lock_open(NULL, if (LF_ISSET(DB_INIT_LOCK) && (ret = lock_open(NULL,
LF_ISSET(DB_CREATE | DB_THREAD), LF_ISSET(DB_CREATE | DB_THREAD),
DB_DEFPERM, dbenv, &dbenv->lk_info)) != 0) mode, dbenv, &dbenv->lk_info)) != 0)
goto err; goto err;
if (LF_ISSET(DB_INIT_LOG) && (ret = log_open(NULL, if (LF_ISSET(DB_INIT_LOG) && (ret = log_open(NULL,
LF_ISSET(DB_CREATE | DB_THREAD), LF_ISSET(DB_CREATE | DB_THREAD),
DB_DEFPERM, dbenv, &dbenv->lg_info)) != 0) mode, dbenv, &dbenv->lg_info)) != 0)
goto err; goto err;
if (LF_ISSET(DB_INIT_MPOOL) && (ret = memp_open(NULL, if (LF_ISSET(DB_INIT_MPOOL) && (ret = memp_open(NULL,
LF_ISSET(DB_CREATE | DB_MPOOL_PRIVATE | DB_NOMMAP | DB_THREAD), 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; goto err;
if (LF_ISSET(DB_INIT_TXN) && (ret = txn_open(NULL, if (LF_ISSET(DB_INIT_TXN) && (ret = txn_open(NULL,
LF_ISSET(DB_CREATE | DB_THREAD | DB_TXN_NOSYNC), LF_ISSET(DB_CREATE | DB_THREAD | DB_TXN_NOSYNC),
DB_DEFPERM, dbenv, &dbenv->tx_info)) != 0) mode, dbenv, &dbenv->tx_info)) != 0)
goto err; 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 (LF_ISSET(DB_INIT_TXN)) {
if ((ret = __bam_init_recover(dbenv)) != 0) if ((ret = __bam_init_recover(dbenv)) != 0)
goto err; goto err;
@ -199,12 +199,12 @@ db_appinit(db_home, db_config, dbenv, flags)
goto err; goto err;
if ((ret = __txn_init_recover(dbenv)) != 0) if ((ret = __txn_init_recover(dbenv)) != 0)
goto err; goto err;
}
/* Run recovery if necessary. */ if (LF_ISSET(DB_RECOVER | DB_RECOVER_FATAL) &&
if (LF_ISSET(DB_RECOVER | DB_RECOVER_FATAL) && (ret = (ret = __db_apprec(dbenv,
__db_apprec(dbenv, LF_ISSET(DB_RECOVER | DB_RECOVER_FATAL))) != 0) LF_ISSET(DB_RECOVER | DB_RECOVER_FATAL))) != 0)
goto err; goto err;
}
return (ret); return (ret);
@ -282,21 +282,21 @@ db_appexit(dbenv)
* it in allocated space. * it in allocated space.
* *
* PUBLIC: int __db_appname __P((DB_ENV *, * 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 int
__db_appname(dbenv, appname, dir, file, fdp, namep) __db_appname(dbenv, appname, dir, file, tmp_oflags, fdp, namep)
DB_ENV *dbenv; DB_ENV *dbenv;
APPNAME appname; APPNAME appname;
const char *dir, *file; const char *dir, *file;
u_int32_t tmp_oflags;
int *fdp; int *fdp;
char **namep; char **namep;
{ {
DB_ENV etmp; DB_ENV etmp;
size_t len; size_t len;
int ret, slash, tmp_create, tmp_free; int data_entry, ret, slash, tmp_create, tmp_free;
const char *a, *b, *c; const char *a, *b, *c;
int data_entry;
char *p, *start; char *p, *start;
a = b = c = NULL; a = b = c = NULL;
@ -349,8 +349,8 @@ __db_appname(dbenv, appname, dir, file, fdp, namep)
* *
* DB_ENV APPNAME RESULT * DB_ENV APPNAME RESULT
* ------------------------------------------- * -------------------------------------------
* null DB_APP_TMP <tmp>/<create> * null DB_APP_TMP* <tmp>/<create>
* set DB_APP_TMP DB_HOME/DB_TMP_DIR/<create> * set DB_APP_TMP* DB_HOME/DB_TMP_DIR/<create>
*/ */
retry: switch (appname) { retry: switch (appname) {
case DB_APP_NONE: case DB_APP_NONE:
@ -431,7 +431,14 @@ done: len =
(c == NULL ? 0 : strlen(c) + 1) + (c == NULL ? 0 : strlen(c) + 1) +
(file == NULL ? 0 : strlen(file) + 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)); __db_err(dbenv, "%s", strerror(ENOMEM));
if (tmp_free) if (tmp_free)
FREES(etmp.db_tmp_dir); FREES(etmp.db_tmp_dir);
@ -460,14 +467,15 @@ done: len =
FREES(etmp.db_tmp_dir); FREES(etmp.db_tmp_dir);
/* Create the file if so requested. */ /* Create the file if so requested. */
if (tmp_create) { if (tmp_create &&
ret = __db_tmp_open(dbenv, start, fdp); (ret = __db_tmp_open(dbenv, tmp_oflags, start, fdp)) != 0) {
FREES(start); FREES(start);
} else { return (ret);
*namep = start;
ret = 0;
} }
return (ret);
if (namep != NULL)
*namep = start;
return (0);
} }
/* /*
@ -478,7 +486,7 @@ static int
__db_home(dbenv, db_home, flags) __db_home(dbenv, db_home, flags)
DB_ENV *dbenv; DB_ENV *dbenv;
const char *db_home; const char *db_home;
int flags; u_int32_t flags;
{ {
const char *p; const char *p;
@ -532,10 +540,12 @@ __db_parse(dbenv, s)
return (ENOMEM); return (ENOMEM);
tp = local_s; tp = local_s;
while ((name = strsep(&tp, " \t")) != NULL && *name == '\0'); while ((name = strsep(&tp, " \t")) != NULL && *name == '\0')
;
if (name == NULL) if (name == NULL)
goto illegal; goto illegal;
while ((value = strsep(&tp, " \t")) != NULL && *value == '\0'); while ((value = strsep(&tp, " \t")) != NULL && *value == '\0')
;
if (value == NULL) { if (value == NULL) {
illegal: ret = EINVAL; illegal: ret = EINVAL;
__db_err(dbenv, "illegal name-value pair: %s", s); __db_err(dbenv, "illegal name-value pair: %s", s);
@ -591,7 +601,7 @@ static char *sTempFolder;
static int static int
__db_tmp_dir(dbenv, flags) __db_tmp_dir(dbenv, flags)
DB_ENV *dbenv; DB_ENV *dbenv;
int flags; u_int32_t flags;
{ {
static const char * list[] = { /* Ordered: see db_appinit(3). */ static const char * list[] = { /* Ordered: see db_appinit(3). */
"/var/tmp", "/var/tmp",
@ -671,49 +681,45 @@ __db_tmp_dir(dbenv, flags)
* Create a temporary file. * Create a temporary file.
*/ */
static int static int
__db_tmp_open(dbenv, dir, fdp) __db_tmp_open(dbenv, flags, path, fdp)
DB_ENV *dbenv; DB_ENV *dbenv;
char *dir; u_int32_t flags;
char *path;
int *fdp; int *fdp;
{ {
#ifdef HAVE_SIGFILLSET #ifdef HAVE_SIGFILLSET
sigset_t set, oset; sigset_t set, oset;
#endif #endif
u_long pid; u_long pid;
size_t len; int mode, isdir, ret;
int isdir, ret; const char *p;
char *trv, buf[MAXPATHLEN]; char *trv;
/* /*
* Check the target directory; if you have six X's and it doesn't * Check the target directory; if you have six X's and it doesn't
* exist, this runs for a *very* long time. * exist, this runs for a *very* long time.
*/ */
if ((ret = __db_exists(dir, &isdir)) != 0) { if ((ret = __db_exists(path, &isdir)) != 0) {
__db_err(dbenv, "%s: %s", dir, strerror(ret)); __db_err(dbenv, "%s: %s", path, strerror(ret));
return (ret); return (ret);
} }
if (!isdir) { if (!isdir) {
__db_err(dbenv, "%s: %s", dir, strerror(EINVAL)); __db_err(dbenv, "%s: %s", path, strerror(EINVAL));
return (EINVAL); return (EINVAL);
} }
/* Build the path. */ /* Build the path. */
#define DB_TRAIL "/XXXXXX" for (trv = path; *trv != '\0'; ++trv)
if ((len = strlen(dir)) + sizeof(DB_TRAIL) > sizeof(buf)) { ;
__db_err(dbenv, *trv = PATH_SEPARATOR[0];
"tmp_open: %s: %s", buf, strerror(ENAMETOOLONG)); for (p = DB_TRAIL; (*++trv = *p) != '\0'; ++p)
return (ENAMETOOLONG); ;
}
(void)strcpy(buf, dir);
(void)strcpy(buf + len, DB_TRAIL);
buf[len] = PATH_SEPARATOR[0]; /* WIN32 */
/* /*
* Replace the X's with the process ID. Pid should be a pid_t, * Replace the X's with the process ID. Pid should be a pid_t,
* but we use unsigned long for portability. * but we use unsigned long for portability.
*/ */
for (pid = getpid(), for (pid = getpid(); *--trv == 'X'; pid /= 10)
trv = buf + len + sizeof(DB_TRAIL) - 1; *--trv == 'X'; pid /= 10)
switch (pid % 10) { switch (pid % 10) {
case 0: *trv = '0'; break; case 0: *trv = '0'; break;
case 1: *trv = '1'; break; case 1: *trv = '1'; break;
@ -728,30 +734,33 @@ __db_tmp_open(dbenv, dir, fdp)
} }
++trv; ++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 * 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 * file isn't left around -- of course, if we drop core in-between
* the calls we'll hang forever, but that's probably okay. ;-} * the calls we'll hang forever, but that's probably okay. ;-}
*/ */
#ifdef HAVE_SIGFILLSET #ifdef HAVE_SIGFILLSET
(void)sigfillset(&set); if (LF_ISSET(DB_TEMPORARY))
(void)sigfillset(&set);
#endif #endif
for (;;) { for (;;) {
#ifdef HAVE_SIGFILLSET #ifdef HAVE_SIGFILLSET
(void)sigprocmask(SIG_BLOCK, &set, &oset); if (LF_ISSET(DB_TEMPORARY))
(void)sigprocmask(SIG_BLOCK, &set, &oset);
#endif #endif
#define DB_TEMPOPEN DB_CREATE | DB_EXCL | DB_TEMPORARY ret = __db_open(path, flags, flags, mode, fdp);
if ((ret = __db_open(buf,
DB_TEMPOPEN, DB_TEMPOPEN, S_IRUSR | S_IWUSR, fdp)) == 0) {
#ifdef HAVE_SIGFILLSET #ifdef HAVE_SIGFILLSET
if (LF_ISSET(DB_TEMPORARY))
(void)sigprocmask(SIG_SETMASK, &oset, NULL); (void)sigprocmask(SIG_SETMASK, &oset, NULL);
#endif #endif
if (ret == 0)
return (0); return (0);
}
#ifdef HAVE_SIGFILLSET
(void)sigprocmask(SIG_SETMASK, &oset, NULL);
#endif
/* /*
* XXX: * XXX:
* If we don't get an EEXIST error, then there's something * 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) { if (ret != EEXIST) {
__db_err(dbenv, __db_err(dbenv,
"tmp_open: %s: %s", buf, strerror(ret)); "tmp_open: %s: %s", path, strerror(ret));
return (ret); return (ret);
} }

View File

@ -1,7 +1,7 @@
/*- /*-
* See the file LICENSE for redistribution information. * See the file LICENSE for redistribution information.
* *
* Copyright (c) 1996, 1997 * Copyright (c) 1996, 1997, 1998
* Sleepycat Software. All rights reserved. * Sleepycat Software. All rights reserved.
*/ */
@ -9,18 +9,17 @@
#ifndef lint #ifndef lint
static const char copyright[] = static const char copyright[] =
"@(#) Copyright (c) 1997\n\ "@(#) Copyright (c) 1996, 1997, 1998\n\
Sleepycat Software Inc. All rights reserved.\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 #endif
#ifndef NO_SYSTEM_INCLUDES #ifndef NO_SYSTEM_INCLUDES
#include <sys/types.h> #include <sys/types.h>
#include <errno.h> #include <errno.h>
#include <time.h>
#include <string.h> #include <string.h>
#include <stdlib.h> #include <time.h>
#endif #endif
#include "db_int.h" #include "db_int.h"
@ -36,18 +35,19 @@ static const char sccsid[] = "@(#)db_apprec.c 10.23 (Sleepycat) 1/17/98";
* __db_apprec -- * __db_apprec --
* Perform recovery. * Perform recovery.
* *
* PUBLIC: int __db_apprec __P((DB_ENV *, int)); * PUBLIC: int __db_apprec __P((DB_ENV *, u_int32_t));
*/ */
int int
__db_apprec(dbenv, flags) __db_apprec(dbenv, flags)
DB_ENV *dbenv; DB_ENV *dbenv;
int flags; u_int32_t flags;
{ {
DBT data; DBT data;
DB_LOG *lp; DB_LOG *lp;
DB_LSN ckp_lsn, first_lsn, lsn; DB_LSN ckp_lsn, first_lsn, lsn;
time_t now; time_t now;
int is_thread, ret; u_int32_t is_thread;
int ret;
void *txninfo; void *txninfo;
lp = dbenv->lg_info; lp = dbenv->lg_info;
@ -91,14 +91,14 @@ __db_apprec(dbenv, flags)
if ((ret = log_get(lp, &ckp_lsn, &data, DB_CHECKPOINT)) != 0) { if ((ret = log_get(lp, &ckp_lsn, &data, DB_CHECKPOINT)) != 0) {
/* /*
* If we don't find a checkpoint, start from the beginning. * If we don't find a checkpoint, start from the beginning.
* If that fails, we're done. Note, we require that there * If that fails, we're done. Note, we do not require that
* be log records if we're performing recovery, and fail if * there be log records if we're performing recovery.
* there aren't.
*/ */
if ((ret = log_get(lp, &ckp_lsn, &data, DB_FIRST)) != 0) { if ((ret = log_get(lp, &ckp_lsn, &data, DB_FIRST)) != 0) {
__db_err(dbenv, "First log record not found");
if (ret == DB_NOTFOUND) if (ret == DB_NOTFOUND)
ret = EINVAL; ret = 0;
else
__db_err(dbenv, "First log record not found");
goto out; goto out;
} }
} }
@ -134,14 +134,17 @@ __db_apprec(dbenv, flags)
} else } else
if ((ret = __log_findckp(lp, &first_lsn)) == DB_NOTFOUND) { if ((ret = __log_findckp(lp, &first_lsn)) == DB_NOTFOUND) {
/* /*
* If recovery was specified, there must be log files. * We don't require that log files exist if recovery
* If we don't find one, it's an error. (This should * was specified.
* have been caught above, when a log_get() of DB_FIRST
* or DB_CHECKPOINT succeeded, but paranoia is good.)
*/ */
ret = EINVAL; ret = 0;
goto out; 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); for (ret = log_get(lp, &lsn, &data, DB_LAST);
ret == 0 && log_compare(&lsn, &first_lsn) > 0; ret == 0 && log_compare(&lsn, &first_lsn) > 0;
ret = log_get(lp, &lsn, &data, DB_PREV)) { ret = log_get(lp, &lsn, &data, DB_PREV)) {
@ -175,21 +178,21 @@ __db_apprec(dbenv, flags)
__log_close_files(lp); __log_close_files(lp);
/* /*
* Now set the maximum transaction id, set the last checkpoint lsn, * Now set the last checkpoint lsn and the current time,
* and the current time. Then take a checkpoint. * take a checkpoint, and reset the txnid.
*/ */
(void)time(&now); (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->last_ckp = ckp_lsn;
dbenv->tx_info->region->time_ckp = (u_int32_t)now; dbenv->tx_info->region->time_ckp = (u_int32_t)now;
if ((ret = txn_checkpoint(dbenv->tx_info, 0, 0)) != 0) if ((ret = txn_checkpoint(dbenv->tx_info, 0, 0)) != 0)
goto out; goto out;
dbenv->tx_info->region->last_txnid = TXN_MINIMUM;
if (dbenv->db_verbose) { if (dbenv->db_verbose) {
__db_err(lp->dbenv, "Recovery complete at %.24s", ctime(&now)); __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", "Maximum transaction id",
(u_long)dbenv->tx_info->region->last_txnid, ((DB_TXNHEAD *)txninfo)->maxid,
"Recovery checkpoint", "Recovery checkpoint",
(u_long)dbenv->tx_info->region->last_ckp.file, (u_long)dbenv->tx_info->region->last_ckp.file,
(u_long)dbenv->tx_info->region->last_ckp.offset); (u_long)dbenv->tx_info->region->last_ckp.offset);

View File

@ -1,14 +1,14 @@
/*- /*-
* See the file LICENSE for redistribution information. * See the file LICENSE for redistribution information.
* *
* Copyright (c) 1996, 1997 * Copyright (c) 1996, 1997, 1998
* Sleepycat Software. All rights reserved. * Sleepycat Software. All rights reserved.
*/ */
#include "config.h" #include "config.h"
#ifndef lint #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 */ #endif /* not lint */
#ifndef NO_SYSTEM_INCLUDES #ifndef NO_SYSTEM_INCLUDES

View File

@ -1,14 +1,14 @@
/*- /*-
* See the file LICENSE for redistribution information. * See the file LICENSE for redistribution information.
* *
* Copyright (c) 1996, 1997 * Copyright (c) 1996, 1997, 1998
* Sleepycat Software. All rights reserved. * Sleepycat Software. All rights reserved.
*/ */
#include "config.h" #include "config.h"
#ifndef lint #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 */ #endif /* not lint */
#ifndef NO_SYSTEM_INCLUDES #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 "db_int.h"
#include "common_ext.h" #include "common_ext.h"
static int __db_keyempty __P((const DB_ENV *));
static int __db_rdonly __P((const DB_ENV *, const char *)); 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. * appears before the assignment in the __db__panic() call.
*/ */
static int __db_ecursor __P((DB *, DB_TXN *, DBC **)); 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_efd __P((DB *, int *));
static int __db_egp __P((DB *, DB_TXN *, DBT *, DBT *, int)); static int __db_egp __P((DB *, DB_TXN *, DBT *, DBT *, u_int32_t));
static int __db_estat __P((DB *, void *, void *(*)(size_t), int)); static int __db_estat __P((DB *, void *, void *(*)(size_t), u_int32_t));
static int __db_esync __P((DB *, int)); static int __db_esync __P((DB *, u_int32_t));
/* /*
* __db_ecursor -- * __db_ecursor --
@ -113,7 +114,7 @@ __db_edel(a, b, c, d)
DB *a; DB *a;
DB_TXN *b; DB_TXN *b;
DBT *c; DBT *c;
int d; u_int32_t d;
{ {
COMPQUIET(a, NULL); COMPQUIET(a, NULL);
COMPQUIET(b, NULL); COMPQUIET(b, NULL);
@ -147,7 +148,7 @@ __db_egp(a, b, c, d, e)
DB *a; DB *a;
DB_TXN *b; DB_TXN *b;
DBT *c, *d; DBT *c, *d;
int e; u_int32_t e;
{ {
COMPQUIET(a, NULL); COMPQUIET(a, NULL);
COMPQUIET(b, NULL); COMPQUIET(b, NULL);
@ -167,7 +168,7 @@ __db_estat(a, b, c, d)
DB *a; DB *a;
void *b; void *b;
void *(*c) __P((size_t)); void *(*c) __P((size_t));
int d; u_int32_t d;
{ {
COMPQUIET(a, NULL); COMPQUIET(a, NULL);
COMPQUIET(b, NULL); COMPQUIET(b, NULL);
@ -184,7 +185,7 @@ __db_estat(a, b, c, d)
static int static int
__db_esync(a, b) __db_esync(a, b)
DB *a; DB *a;
int b; u_int32_t b;
{ {
COMPQUIET(a, NULL); COMPQUIET(a, NULL);
COMPQUIET(b, 0); COMPQUIET(b, 0);
@ -208,6 +209,10 @@ __db_panic(dbp)
* *
* We should call mpool and have it shut down the file, so we get * We should call mpool and have it shut down the file, so we get
* other processes sharing this file as well. * other processes sharing this file as well.
*
* Chaos reigns within.
* Reflect, repent, and reboot.
* Order shall return.
*/ */
dbp->cursor = __db_ecursor; dbp->cursor = __db_ecursor;
dbp->del = __db_edel; dbp->del = __db_edel;
@ -235,13 +240,13 @@ __db_panic(dbp)
* __db_fchk -- * __db_fchk --
* General flags checking routine. * 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 int
__db_fchk(dbenv, name, flags, ok_flags) __db_fchk(dbenv, name, flags, ok_flags)
DB_ENV *dbenv; DB_ENV *dbenv;
const char *name; const char *name;
int flags, ok_flags; u_int32_t flags, ok_flags;
{ {
DB_CHECK_FLAGS(dbenv, name, flags, ok_flags); DB_CHECK_FLAGS(dbenv, name, flags, ok_flags);
return (0); return (0);
@ -251,13 +256,14 @@ __db_fchk(dbenv, name, flags, ok_flags)
* __db_fcchk -- * __db_fcchk --
* General combination flags checking routine. * 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 int
__db_fcchk(dbenv, name, flags, flag1, flag2) __db_fcchk(dbenv, name, flags, flag1, flag2)
DB_ENV *dbenv; DB_ENV *dbenv;
const char *name; const char *name;
int flags, flag1, flag2; u_int32_t flags, flag1, flag2;
{ {
DB_CHECK_FCOMBO(dbenv, name, flags, flag1, flag2); DB_CHECK_FCOMBO(dbenv, name, flags, flag1, flag2);
return (0); return (0);
@ -267,12 +273,13 @@ __db_fcchk(dbenv, name, flags, flag1, flag2)
* __db_cdelchk -- * __db_cdelchk --
* Common cursor delete argument checking routine. * 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 int
__db_cdelchk(dbp, flags, isrdonly, isvalid) __db_cdelchk(dbp, flags, isrdonly, isvalid)
const DB *dbp; const DB *dbp;
int flags, isrdonly, isvalid; u_int32_t flags;
int isrdonly, isvalid;
{ {
/* Check for changes to a read-only tree. */ /* Check for changes to a read-only tree. */
if (isrdonly) if (isrdonly)
@ -292,17 +299,18 @@ __db_cdelchk(dbp, flags, isrdonly, isvalid)
* __db_cgetchk -- * __db_cgetchk --
* Common cursor get argument checking routine. * 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 int
__db_cgetchk(dbp, key, data, flags, isvalid) __db_cgetchk(dbp, key, data, flags, isvalid)
const DB *dbp; const DB *dbp;
DBT *key, *data; 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. */ /* Check for invalid dbc->c_get() function flags. */
switch (flags) { switch (flags) {
@ -311,10 +319,13 @@ __db_cgetchk(dbp, key, data, flags, isvalid)
case DB_LAST: case DB_LAST:
case DB_NEXT: case DB_NEXT:
case DB_PREV: case DB_PREV:
key_flags = 1;
break;
case DB_SET_RANGE: case DB_SET_RANGE:
check_key = 1; key_einval = key_flags = 1;
break; break;
case DB_SET: case DB_SET:
key_einval = 1;
break; break;
case DB_GET_RECNO: case DB_GET_RECNO:
if (!F_ISSET(dbp, DB_BT_RECNUM)) if (!F_ISSET(dbp, DB_BT_RECNUM))
@ -323,14 +334,14 @@ __db_cgetchk(dbp, key, data, flags, isvalid)
case DB_SET_RECNO: case DB_SET_RECNO:
if (!F_ISSET(dbp, DB_BT_RECNUM)) if (!F_ISSET(dbp, DB_BT_RECNUM))
goto err; goto err;
check_key = 1; key_einval = key_flags = 1;
break; break;
default: default:
err: return (__db_ferr(dbp->dbenv, "c_get", 0)); err: return (__db_ferr(dbp->dbenv, "c_get", 0));
} }
/* Check for invalid key/data flags. */ /* Check for invalid key/data flags. */
if (check_key) if (key_flags)
DB_CHECK_FLAGS(dbp->dbenv, "key", key->flags, DB_CHECK_FLAGS(dbp->dbenv, "key", key->flags,
DB_DBT_MALLOC | DB_DBT_USERMEM | DB_DBT_PARTIAL); DB_DBT_MALLOC | DB_DBT_USERMEM | DB_DBT_PARTIAL);
DB_CHECK_FLAGS(dbp->dbenv, "data", data->flags, 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(dbp, DB_AM_THREAD)) {
if (!F_ISSET(data, DB_DBT_USERMEM | DB_DBT_MALLOC)) if (!F_ISSET(data, DB_DBT_USERMEM | DB_DBT_MALLOC))
return (__db_ferr(dbp->dbenv, "threaded data", 1)); return (__db_ferr(dbp->dbenv, "threaded data", 1));
if (check_key && if (key_flags &&
!F_ISSET(key, DB_DBT_USERMEM | DB_DBT_MALLOC)) !F_ISSET(key, DB_DBT_USERMEM | DB_DBT_MALLOC))
return (__db_ferr(dbp->dbenv, "threaded key", 1)); 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 * The cursor must be initialized for DB_CURRENT, return -1 for an
* invalid cursor, otherwise 0. * invalid cursor, otherwise 0.
@ -357,23 +372,24 @@ err: return (__db_ferr(dbp->dbenv, "c_get", 0));
* Common cursor put argument checking routine. * Common cursor put argument checking routine.
* *
* PUBLIC: int __db_cputchk __P((const DB *, * PUBLIC: int __db_cputchk __P((const DB *,
* PUBLIC: const DBT *, DBT *, int, int, int)); * PUBLIC: const DBT *, DBT *, u_int32_t, int, int));
*/ */
int int
__db_cputchk(dbp, key, data, flags, isrdonly, isvalid) __db_cputchk(dbp, key, data, flags, isrdonly, isvalid)
const DB *dbp; const DB *dbp;
const DBT *key; const DBT *key;
DBT *data; 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. */ /* Check for changes to a read-only tree. */
if (isrdonly) if (isrdonly)
return (__db_rdonly(dbp->dbenv, "c_put")); return (__db_rdonly(dbp->dbenv, "c_put"));
/* Check for invalid dbc->c_put() function flags. */ /* Check for invalid dbc->c_put() function flags. */
check_key = 0; key_einval = key_flags = 0;
switch (flags) { switch (flags) {
case DB_AFTER: case DB_AFTER:
case DB_BEFORE: case DB_BEFORE:
@ -388,19 +404,23 @@ __db_cputchk(dbp, key, data, flags, isrdonly, isvalid)
case DB_KEYLAST: case DB_KEYLAST:
if (dbp->type == DB_RECNO) if (dbp->type == DB_RECNO)
goto err; goto err;
check_key = 1; key_einval = key_flags = 1;
break; break;
default: default:
err: return (__db_ferr(dbp->dbenv, "c_put", 0)); err: return (__db_ferr(dbp->dbenv, "c_put", 0));
} }
/* Check for invalid key/data flags. */ /* Check for invalid key/data flags. */
if (check_key) if (key_flags)
DB_CHECK_FLAGS(dbp->dbenv, "key", key->flags, DB_CHECK_FLAGS(dbp->dbenv, "key", key->flags,
DB_DBT_MALLOC | DB_DBT_USERMEM | DB_DBT_PARTIAL); DB_DBT_MALLOC | DB_DBT_USERMEM | DB_DBT_PARTIAL);
DB_CHECK_FLAGS(dbp->dbenv, "data", data->flags, DB_CHECK_FLAGS(dbp->dbenv, "data", data->flags,
DB_DBT_MALLOC | DB_DBT_USERMEM | DB_DBT_PARTIAL); 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 * The cursor must be initialized for anything other than DB_KEYFIRST
* and DB_KEYLAST, return -1 for an invalid cursor, otherwise 0. * 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 -- * __db_delchk --
* Common delete argument checking routine. * 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 int
__db_delchk(dbp, flags, isrdonly) __db_delchk(dbp, key, flags, isrdonly)
const DB *dbp; const DB *dbp;
int flags, isrdonly; DBT *key;
u_int32_t flags;
int isrdonly;
{ {
/* Check for changes to a read-only tree. */ /* Check for changes to a read-only tree. */
if (isrdonly) if (isrdonly)
@ -427,6 +449,10 @@ __db_delchk(dbp, flags, isrdonly)
/* Check for invalid db->del() function flags. */ /* Check for invalid db->del() function flags. */
DB_CHECK_FLAGS(dbp->dbenv, "delete", flags, 0); 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); return (0);
} }
@ -434,14 +460,14 @@ __db_delchk(dbp, flags, isrdonly)
* __db_getchk -- * __db_getchk --
* Common get argument checking routine. * 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 int
__db_getchk(dbp, key, data, flags) __db_getchk(dbp, key, data, flags)
const DB *dbp; const DB *dbp;
const DBT *key; const DBT *key;
DBT *data; DBT *data;
int flags; u_int32_t flags;
{ {
/* Check for invalid db->get() function flags. */ /* Check for invalid db->get() function flags. */
DB_CHECK_FLAGS(dbp->dbenv, DB_CHECK_FLAGS(dbp->dbenv,
@ -457,6 +483,10 @@ __db_getchk(dbp, key, data, flags)
!F_ISSET(data, DB_DBT_MALLOC | DB_DBT_USERMEM)) !F_ISSET(data, DB_DBT_MALLOC | DB_DBT_USERMEM))
return (__db_ferr(dbp->dbenv, "threaded data", 1)); 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); return (0);
} }
@ -464,14 +494,16 @@ __db_getchk(dbp, key, data, flags)
* __db_putchk -- * __db_putchk --
* Common put argument checking routine. * 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 int
__db_putchk(dbp, key, data, flags, isrdonly, isdup) __db_putchk(dbp, key, data, flags, isrdonly, isdup)
const DB *dbp; const DB *dbp;
DBT *key; DBT *key;
const DBT *data; const DBT *data;
int flags, isrdonly, isdup; u_int32_t flags;
int isrdonly, isdup;
{ {
/* Check for changes to a read-only tree. */ /* Check for changes to a read-only tree. */
if (isrdonly) if (isrdonly)
@ -488,12 +520,17 @@ __db_putchk(dbp, key, data, flags, isrdonly, isdup)
DB_CHECK_FCOMBO(dbp->dbenv, DB_CHECK_FCOMBO(dbp->dbenv,
"data", data->flags, DB_DBT_MALLOC, DB_DBT_USERMEM); "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. */ /* Check for partial puts in the presence of duplicates. */
if (isdup && F_ISSET(data, DB_DBT_PARTIAL)) { if (isdup && F_ISSET(data, DB_DBT_PARTIAL)) {
__db_err(dbp->dbenv, __db_err(dbp->dbenv,
"a partial put in the presence of duplicates requires a cursor operation"); "a partial put in the presence of duplicates requires a cursor operation");
return (EINVAL); return (EINVAL);
} }
return (0); return (0);
} }
@ -501,12 +538,12 @@ __db_putchk(dbp, key, data, flags, isrdonly, isdup)
* __db_statchk -- * __db_statchk --
* Common stat argument checking routine. * Common stat argument checking routine.
* *
* PUBLIC: int __db_statchk __P((const DB *, int)); * PUBLIC: int __db_statchk __P((const DB *, u_int32_t));
*/ */
int int
__db_statchk(dbp, flags) __db_statchk(dbp, flags)
const DB *dbp; const DB *dbp;
int flags; u_int32_t flags;
{ {
/* Check for invalid db->stat() function flags. */ /* Check for invalid db->stat() function flags. */
DB_CHECK_FLAGS(dbp->dbenv, "stat", flags, DB_RECORDCOUNT); DB_CHECK_FLAGS(dbp->dbenv, "stat", flags, DB_RECORDCOUNT);
@ -522,12 +559,12 @@ __db_statchk(dbp, flags)
* __db_syncchk -- * __db_syncchk --
* Common sync argument checking routine. * Common sync argument checking routine.
* *
* PUBLIC: int __db_syncchk __P((const DB *, int)); * PUBLIC: int __db_syncchk __P((const DB *, u_int32_t));
*/ */
int int
__db_syncchk(dbp, flags) __db_syncchk(dbp, flags)
const DB *dbp; const DB *dbp;
int flags; u_int32_t flags;
{ {
/* Check for invalid db->sync() function flags. */ /* Check for invalid db->sync() function flags. */
DB_CHECK_FLAGS(dbp->dbenv, "sync", flags, 0); 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)); * PUBLIC: int __db_ferr __P((const DB_ENV *, const char *, int));
*/ */
int int
__db_ferr(dbenv, name, combo) __db_ferr(dbenv, name, iscombo)
const DB_ENV *dbenv; const DB_ENV *dbenv;
const char *name; const char *name;
int combo; int iscombo;
{ {
__db_err(dbenv, "illegal flag %sspecified to %s", __db_err(dbenv, "illegal flag %sspecified to %s",
combo ? "combination " : "", name); iscombo ? "combination " : "", name);
return (EINVAL); return (EINVAL);
} }
@ -564,3 +601,15 @@ __db_rdonly(dbenv, name)
__db_err(dbenv, "%s: attempt to modify a read-only tree", name); __db_err(dbenv, "%s: attempt to modify a read-only tree", name);
return (EACCES); 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);
}

View File

@ -1,7 +1,7 @@
/*- /*-
* See the file LICENSE for redistribution information. * See the file LICENSE for redistribution information.
* *
* Copyright (c) 1996, 1997 * Copyright (c) 1996, 1997, 1998
* Sleepycat Software. All rights reserved. * Sleepycat Software. All rights reserved.
*/ */
/* /*
@ -43,7 +43,7 @@
#include "config.h" #include "config.h"
#ifndef lint #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 */ #endif /* not lint */
#ifndef NO_SYSTEM_INCLUDES #ifndef NO_SYSTEM_INCLUDES
@ -63,6 +63,7 @@ __db_log2(num)
u_int32_t i, limit; u_int32_t i, limit;
limit = 1; limit = 1;
for (i = 0; limit < num; limit = limit << 1, i++); for (i = 0; limit < num; limit = limit << 1, i++)
;
return (i); return (i);
} }

File diff suppressed because it is too large Load Diff

View File

@ -1,21 +1,21 @@
/*- /*-
* See the file LICENSE for redistribution information. * See the file LICENSE for redistribution information.
* *
* Copyright (c) 1996, 1997 * Copyright (c) 1996, 1997, 1998
* Sleepycat Software. All rights reserved. * Sleepycat Software. All rights reserved.
*/ */
#include "config.h" #include "config.h"
#ifndef lint #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 */ #endif /* not lint */
#ifndef NO_SYSTEM_INCLUDES #ifndef NO_SYSTEM_INCLUDES
#include <sys/types.h> #include <sys/types.h>
#include <errno.h> #include <errno.h>
#include <stdio.h> #include <string.h>
#endif #endif
#include "db_int.h" #include "db_int.h"
@ -109,11 +109,13 @@ __db_shalloc(p, len, align, retp)
*(void **)retp = rp; *(void **)retp = rp;
#define SHALLOC_FRAGMENT 32
/* /*
* If there are at least 32 bytes of additional memory, divide * If there are at least SHALLOC_FRAGMENT additional bytes of
* the chunk into two chunks. * 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 = rp;
*--sp = elp->len - *--sp = elp->len -
((u_int8_t *)rp - (u_int8_t *)&elp->links); ((u_int8_t *)rp - (u_int8_t *)&elp->links);
@ -136,7 +138,7 @@ __db_shalloc(p, len, align, retp)
return (0); 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); return (ENOMEM);
} }
@ -159,12 +161,18 @@ __db_shalloc_free(regionp, ptr)
* Step back over flagged length fields to find the beginning of * Step back over flagged length fields to find the beginning of
* the object and its real size. * 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; ptr = sp;
newp = (struct __data *)((u_int8_t *)ptr - sizeof(size_t)); newp = (struct __data *)((u_int8_t *)ptr - sizeof(size_t));
free_size = newp->len; 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. * Walk the list, looking for where this entry goes.
* *
@ -177,7 +185,8 @@ __db_shalloc_free(regionp, ptr)
hp = (struct __head *)regionp; hp = (struct __head *)regionp;
for (elp = SH_LIST_FIRST(hp, __data), lastp = NULL; for (elp = SH_LIST_FIRST(hp, __data), lastp = NULL;
elp != NULL && (void *)elp < (void *)ptr; 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 * 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 * Step back over flagged length fields to find the beginning of
* the object and its real size. * 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)); elp = (struct __data *)((u_int8_t *)sp - sizeof(size_t));
return (elp->len); return (elp->len);
} }
#ifdef DEBUG
/* /*
* __db_shalloc_dump -- * __db_shalloc_dump --
* *
* PUBLIC: void __db_shalloc_dump __P((FILE *, void *)); * PUBLIC: void __db_shalloc_dump __P((void *, FILE *));
*/ */
void void
__db_shalloc_dump(fp, addr) __db_shalloc_dump(addr, fp)
FILE *fp;
void *addr; void *addr;
FILE *fp;
{ {
struct __data *elp; struct __data *elp;
/* Make it easy to call from the debugger. */
if (fp == NULL) if (fp == NULL)
fp = stderr; fp = stderr;
fprintf(fp, "%s\nMemory free list\n", DB_LINE);
for (elp = SH_LIST_FIRST((struct __head *)addr, __data); for (elp = SH_LIST_FIRST((struct __head *)addr, __data);
elp != NULL; elp != NULL;
elp = SH_LIST_NEXT(elp, links, __data)) elp = SH_LIST_NEXT(elp, links, __data))
fprintf(fp, "%#lx: %lu\t", (u_long)elp, (u_long)elp->len); fprintf(fp, "%#lx: %lu\t", (u_long)elp, (u_long)elp->len);
fprintf(fp, "\n"); fprintf(fp, "\n");
} }
#endif

View File

@ -1,14 +1,14 @@
/*- /*-
* See the file LICENSE for redistribution information. * See the file LICENSE for redistribution information.
* *
* Copyright (c) 1996, 1997 * Copyright (c) 1996, 1997, 1998
* Sleepycat Software. All rights reserved. * Sleepycat Software. All rights reserved.
*/ */
#include "config.h" #include "config.h"
#ifndef lint #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 */ #endif /* not lint */
#ifndef NO_SYSTEM_INCLUDES #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 "shqueue.h"
#include "common_ext.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 { static const struct {
u_int power; u_int32_t power;
u_int prime; u_int32_t prime;
} list[] = { } list[] = {
{ 64, 67}, { 64, 67}, /* 2^6 */
{ 128, 131}, { 128, 131}, /* 2^7 */
{ 256, 257}, { 256, 257}, /* 2^8 */
{ 512, 521}, { 512, 521}, /* 2^9 */
{1024, 1031}, { 1024, 1031}, /* 2^10 */
{2048, 2053}, { 2048, 2053}, /* 2^11 */
{4096, 4099}, { 4096, 4099}, /* 2^12 */
{8192, 8191}, { 8192, 8191}, /* 2^13 */
{0, 0} { 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 -- * __db_tablesize --
* Choose a size for the hash table. * Choose a size for the hash table.
* *
* PUBLIC: int __db_tablesize __P((u_int)); * PUBLIC: int __db_tablesize __P((u_int32_t));
*/ */
int int
__db_tablesize(n_buckets) __db_tablesize(n_buckets)
u_int n_buckets; u_int32_t n_buckets;
{ {
int i; int i;
/* /*
* We try to be clever about how big we make the hash tables. Pick * We try to be clever about how big we make the hash tables. Use a
* a prime number close to the "suggested" number of elements that * prime number close to the "suggested" number of elements that will
* will be in the hash table. We shoot for minimum collisions (i.e. * be in the hash table. Use 64 as the minimum hash table size.
* one element in each bucket). We use 64 as the minimum table size.
* *
* Ref: Sedgewick, Algorithms in C, "Hash Functions" * Ref: Sedgewick, Algorithms in C, "Hash Functions"
*/ */
@ -73,14 +109,14 @@ __db_tablesize(n_buckets)
* __db_hashinit -- * __db_hashinit --
* Initialize a hash table that resides in shared memory. * 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 void
__db_hashinit(begin, nelements) __db_hashinit(begin, nelements)
void *begin; void *begin;
int nelements; u_int32_t nelements;
{ {
int i; u_int32_t i;
SH_TAILQ_HEAD(hash_head) *headp; SH_TAILQ_HEAD(hash_head) *headp;
headp = (struct hash_head *)begin; headp = (struct hash_head *)begin;

View File

@ -24,6 +24,9 @@
/* Define to `unsigned' if <sys/types.h> doesn't define. */ /* Define to `unsigned' if <sys/types.h> doesn't define. */
/* #undef size_t */ /* #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 if you have the ANSI C header files. */
#define STDC_HEADERS 1 #define STDC_HEADERS 1
@ -36,14 +39,17 @@
/* Define if you want a debugging version. */ /* Define if you want a debugging version. */
/* #undef DEBUG */ /* #undef DEBUG */
/* Define if you want a version with run-time diagnostic checking. */
/* #undef DIAGNOSTIC */
/* Define if you have sigfillset (and sigprocmask). */ /* Define if you have sigfillset (and sigprocmask). */
#define HAVE_SIGFILLSET 1 #define HAVE_SIGFILLSET 1
/* Define if seeking to 64-bit file offsets requires the _llseek() call. */ /* Define if building on AIX, HP, Solaris to get big-file environment. */
/* #undef HAVE_LLSEEK */ /* #undef HAVE_FILE_OFFSET_BITS */
#ifdef HAVE_FILE_OFFSET_BITS
/* Define if seeking to 64-bit file offsets requires the _lseeki64() call. */ #define _FILE_OFFSET_BITS 64
/* #undef HAVE_LSEEKI */ #endif
/* Define if you have spinlocks. */ /* Define if you have spinlocks. */
/* #undef HAVE_SPINLOCKS */ /* #undef HAVE_SPINLOCKS */
@ -51,6 +57,12 @@
/* Define if you want to use mc68020/gcc assembly spinlocks. */ /* Define if you want to use mc68020/gcc assembly spinlocks. */
/* #undef HAVE_ASSEM_MC68020_GCC */ /* #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. */ /* Define if you want to use sparc/gcc assembly spinlocks. */
/* #undef HAVE_ASSEM_SPARC_GCC */ /* #undef HAVE_ASSEM_SPARC_GCC */
@ -69,6 +81,9 @@
/* Define if you have the SGI abilock_t spinlocks. */ /* Define if you have the SGI abilock_t spinlocks. */
/* #undef HAVE_FUNC_SGI */ /* #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. */ /* Define if you have the Solaris mutex_t spinlocks. */
/* #undef HAVE_FUNC_SOLARIS */ /* #undef HAVE_FUNC_SOLARIS */
@ -102,12 +117,12 @@
/* Define if you have the select function. */ /* Define if you have the select function. */
#define HAVE_SELECT 1 #define HAVE_SELECT 1
/* Define if you have the shmget function. */
#define HAVE_SHMGET 1
/* Define if you have the snprintf function. */ /* Define if you have the snprintf function. */
#define HAVE_SNPRINTF 1 #define HAVE_SNPRINTF 1
/* Define if you have the strdup function. */
#define HAVE_STRDUP 1
/* Define if you have the strerror function. */ /* Define if you have the strerror function. */
#define HAVE_STRERROR 1 #define HAVE_STRERROR 1

245
db2/db.h
View File

@ -1,10 +1,10 @@
/*- /*-
* See the file LICENSE for redistribution information. * See the file LICENSE for redistribution information.
* *
* Copyright (c) 1996, 1997 * Copyright (c) 1996, 1997, 1998
* Sleepycat Software. All rights reserved. * 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_ #ifndef _DB_H_
@ -54,8 +54,7 @@
* *
* !!! * !!!
* We also provide the standard u_int, u_long etc., if they're not provided * 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 * by the system.
* need them.
*/ */
#ifndef __BIT_TYPES_DEFINED__ #ifndef __BIT_TYPES_DEFINED__
#define __BIT_TYPES_DEFINED__ #define __BIT_TYPES_DEFINED__
@ -72,9 +71,9 @@
#define DB_VERSION_MAJOR 2 #define DB_VERSION_MAJOR 2
#define DB_VERSION_MINOR 3 #define DB_VERSION_MINOR 4
#define DB_VERSION_PATCH 16 #define DB_VERSION_PATCH 14
#define DB_VERSION_STRING "Sleepycat Software: DB 2.3.16: (1/19/98)" #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_int32_t db_pgno_t; /* Page number type. */
typedef u_int16_t db_indx_t; /* Page offset 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_dbt; typedef struct __db_dbt DBT;
struct __db_env; typedef struct __db_env DB_ENV; struct __db_env; typedef struct __db_env DB_ENV;
struct __db_info; typedef struct __db_info DB_INFO; 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_lockregion; typedef struct __db_lockregion DB_LOCKREGION;
struct __db_lockreq; typedef struct __db_lockreq DB_LOCKREQ; struct __db_lockreq; typedef struct __db_lockreq DB_LOCKREQ;
struct __db_locktab; typedef struct __db_locktab DB_LOCKTAB; 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_log_stat; typedef struct __db_log_stat DB_LOG_STAT;
struct __db_lsn; typedef struct __db_lsn DB_LSN; struct __db_lsn; typedef struct __db_lsn DB_LSN;
struct __db_mpool; typedef struct __db_mpool DB_MPOOL; 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_fstat;typedef struct __db_mpool_fstat DB_MPOOL_FSTAT;
struct __db_mpool_stat; typedef struct __db_mpool_stat DB_MPOOL_STAT; struct __db_mpool_stat; typedef struct __db_mpool_stat DB_MPOOL_STAT;
struct __db_mpoolfile; typedef struct __db_mpoolfile DB_MPOOLFILE; 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 * 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. * 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_CLOSE 2 /* POSIX 1003.1 close. */
#define DB_FUNC_DIRFREE 3 /* DB: free directory list. */ #define DB_FUNC_DIRFREE 3 /* DB: free directory list. */
#define DB_FUNC_DIRLIST 4 /* DB: create 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_REALLOC 13 /* ANSI C realloc. */
#define DB_FUNC_SEEK 14 /* POSIX 1003.1 lseek. */ #define DB_FUNC_SEEK 14 /* POSIX 1003.1 lseek. */
#define DB_FUNC_SLEEP 15 /* DB: sleep secs/usecs. */ #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_UNLINK 17 /* POSIX 1003.1 unlink. */
#define DB_FUNC_UNMAP 18 /* DB: unmap shared memory file. */ #define DB_FUNC_UNMAP 18 /* DB: unmap shared memory file. */
#define DB_FUNC_WRITE 19 /* POSIX 1003.1 write. */ #define DB_FUNC_WRITE 19 /* POSIX 1003.1 write. */
#define DB_FUNC_YIELD 20 /* DB: yield thread to scheduler. */ #define DB_FUNC_YIELD 20 /* DB: yield thread to scheduler. */
#define DB_TSL_SPINS 21 /* DB: initialize spin count. */ #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. * Database configuration and initialization.
@ -162,52 +169,51 @@ struct __db_dbt {
/* /*
* Flags understood by both db_open(3) and db_appinit(3). * Flags understood by both db_open(3) and db_appinit(3).
*/ */
#define DB_CREATE 0x00001 /* O_CREAT: create file as necessary. */ #define DB_CREATE 0x000001 /* O_CREAT: create file as necessary. */
#define DB_NOMMAP 0x00002 /* Don't mmap underlying file. */ #define DB_NOMMAP 0x000002 /* Don't mmap underlying file. */
#define DB_THREAD 0x00004 /* Free-thread DB package handles. */ #define DB_THREAD 0x000004 /* Free-thread DB package handles. */
/* /*
* Flags understood by db_appinit(3). * Flags understood by db_appinit(3).
*
* DB_MUTEXDEBUG is internal only, and not documented.
*/ */
/* 0x00007 COMMON MASK. */ /* 0x000007 COMMON MASK. */
#define DB_INIT_LOCK 0x00008 /* Initialize locking. */ #define DB_INIT_LOCK 0x000008 /* Initialize locking. */
#define DB_INIT_LOG 0x00010 /* Initialize logging. */ #define DB_INIT_LOG 0x000010 /* Initialize logging. */
#define DB_INIT_MPOOL 0x00020 /* Initialize mpool. */ #define DB_INIT_MPOOL 0x000020 /* Initialize mpool. */
#define DB_INIT_TXN 0x00040 /* Initialize transactions. */ #define DB_INIT_TXN 0x000040 /* Initialize transactions. */
#define DB_MPOOL_PRIVATE 0x00080 /* Mpool: private memory pool. */ #define DB_MPOOL_PRIVATE 0x000080 /* Mpool: private memory pool. */
#define DB_MUTEXDEBUG 0x00100 /* Do not get/set mutexes in regions. */ #define __UNUSED_100 0x000100
#define DB_RECOVER 0x00200 /* Run normal recovery. */ #define DB_RECOVER 0x000200 /* Run normal recovery. */
#define DB_RECOVER_FATAL 0x00400 /* Run catastrophic recovery. */ #define DB_RECOVER_FATAL 0x000400 /* Run catastrophic recovery. */
#define DB_TXN_NOSYNC 0x00800 /* Do not sync log on commit. */ #define DB_TXN_NOSYNC 0x000800 /* Do not sync log on commit. */
#define DB_USE_ENVIRON 0x01000 /* Use the environment. */ #define DB_USE_ENVIRON 0x001000 /* Use the environment. */
#define DB_USE_ENVIRON_ROOT 0x02000 /* Use the environment if root. */ #define DB_USE_ENVIRON_ROOT 0x002000 /* Use the environment if root. */
/* CURRENTLY UNUSED LOCK FLAGS. */ /* CURRENTLY UNUSED LOCK FLAGS. */
#define DB_TXN_LOCK_2PL 0x00000 /* Two-phase locking. */ #define DB_TXN_LOCK_2PL 0x000000 /* Two-phase locking. */
#define DB_TXN_LOCK_OPTIMISTIC 0x00000 /* Optimistic locking. */ #define DB_TXN_LOCK_OPTIMIST 0x000000 /* Optimistic locking. */
#define DB_TXN_LOCK_MASK 0x00000 /* Lock flags mask. */ #define DB_TXN_LOCK_MASK 0x000000 /* Lock flags mask. */
/* CURRENTLY UNUSED LOG FLAGS. */ /* CURRENTLY UNUSED LOG FLAGS. */
#define DB_TXN_LOG_REDO 0x00000 /* Redo-only logging. */ #define DB_TXN_LOG_REDO 0x000000 /* Redo-only logging. */
#define DB_TXN_LOG_UNDO 0x00000 /* Undo-only logging. */ #define DB_TXN_LOG_UNDO 0x000000 /* Undo-only logging. */
#define DB_TXN_LOG_UNDOREDO 0x00000 /* Undo/redo write-ahead logging. */ #define DB_TXN_LOG_UNDOREDO 0x000000 /* Undo/redo write-ahead logging. */
#define DB_TXN_LOG_MASK 0x00000 /* Log flags mask. */ #define DB_TXN_LOG_MASK 0x000000 /* Log flags mask. */
/* /*
* Flags understood by db_open(3). * Flags understood by db_open(3).
* *
* DB_EXCL and DB_TEMPORARY are internal only, and not documented. * DB_EXCL and DB_TEMPORARY are internal only, and are not documented.
* DB_SEQUENTIAL is currently internal, but likely to be exported some day. * DB_SEQUENTIAL is currently internal, but may be exported some day.
*/ */
/* 0x00007 COMMON MASK. */ /* 0x000007 COMMON MASK. */
/* 0x07fff ALREADY USED. */ /* 0x003fff ALREADY USED. */
#define DB_EXCL 0x08000 /* O_EXCL: exclusive open. */ #define __UNUSED_4000 0x004000
#define DB_RDONLY 0x10000 /* O_RDONLY: read-only. */ #define DB_EXCL 0x008000 /* O_EXCL: exclusive open. */
#define DB_SEQUENTIAL 0x20000 /* Indicate sequential access. */ #define DB_RDONLY 0x010000 /* O_RDONLY: read-only. */
#define DB_TEMPORARY 0x40000 /* Remove on last close. */ #define DB_SEQUENTIAL 0x020000 /* Indicate sequential access. */
#define DB_TRUNCATE 0x80000 /* O_TRUNCATE: replace existing DB. */ #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 * Deadlock detector modes; used in the DBENV structure to configure the
@ -240,9 +246,9 @@ struct __db_env {
/* Locking. */ /* Locking. */
DB_LOCKTAB *lk_info; /* Return from lock_open(). */ DB_LOCKTAB *lk_info; /* Return from lock_open(). */
u_int8_t *lk_conflicts; /* Two dimensional conflict matrix. */ u_int8_t *lk_conflicts; /* Two dimensional conflict matrix. */
int lk_modes; /* Number of lock modes in table. */ u_int32_t lk_modes; /* Number of lock modes in table. */
u_int lk_max; /* Maximum number of locks. */ u_int32_t lk_max; /* Maximum number of locks. */
u_int32_t lk_detect; /* Deadlock detect on every conflict. */ u_int32_t lk_detect; /* Deadlock detect on all conflicts. */
/* Logging. */ /* Logging. */
DB_LOG *lg_info; /* Return from log_open(). */ DB_LOG *lg_info; /* Return from log_open(). */
@ -255,7 +261,7 @@ struct __db_env {
/* Transactions. */ /* Transactions. */
DB_TXNMGR *tx_info; /* Return from txn_open(). */ 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. */ int (*tx_recover) /* Dispatch function for recovery. */
__P((DB_LOG *, DBT *, DB_LSN *, int, void *)); __P((DB_LOG *, DBT *, DB_LSN *, int, void *));
@ -300,17 +306,17 @@ struct __db_info {
void *(*db_malloc) __P((size_t)); void *(*db_malloc) __P((size_t));
/* Btree access method. */ /* Btree access method. */
int bt_maxkey; /* Maximum keys per page. */ u_int32_t bt_maxkey; /* Maximum keys per page. */
int bt_minkey; /* Minimum keys per page. */ u_int32_t bt_minkey; /* Minimum keys per page. */
int (*bt_compare) /* Comparison function. */ int (*bt_compare) /* Comparison function. */
__P((const DBT *, const DBT *)); __P((const DBT *, const DBT *));
size_t (*bt_prefix) /* Prefix function. */ size_t (*bt_prefix) /* Prefix function. */
__P((const DBT *, const DBT *)); __P((const DBT *, const DBT *));
/* Hash access method. */ /* Hash access method. */
unsigned int h_ffactor; /* Fill factor. */ u_int32_t h_ffactor; /* Fill factor. */
unsigned int h_nelem; /* Number of elements. */ u_int32_t h_nelem; /* Number of elements. */
u_int32_t (*h_hash) /* Hash function. */ u_int32_t (*h_hash) /* Hash function. */
__P((const void *, u_int32_t)); __P((const void *, u_int32_t));
/* Recno access method. */ /* Recno access method. */
@ -353,6 +359,7 @@ struct __db_info {
#define DB_SET 0x010000 /* c_get(), log_get() */ #define DB_SET 0x010000 /* c_get(), log_get() */
#define DB_SET_RANGE 0x020000 /* c_get() */ #define DB_SET_RANGE 0x020000 /* c_get() */
#define DB_SET_RECNO 0x040000 /* c_get() */ #define DB_SET_RECNO 0x040000 /* c_get() */
#define DB_CURLSN 0x080000 /* log_put() */
/* /*
* DB (user visible) error return codes. * DB (user visible) error return codes.
@ -435,14 +442,14 @@ struct __db {
void *(*db_malloc) __P((size_t)); void *(*db_malloc) __P((size_t));
/* Functions. */ /* Functions. */
int (*close) __P((DB *, int)); int (*close) __P((DB *, u_int32_t));
int (*cursor) __P((DB *, DB_TXN *, DBC **)); 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 (*fd) __P((DB *, int *));
int (*get) __P((DB *, DB_TXN *, DBT *, DBT *, int)); int (*get) __P((DB *, DB_TXN *, DBT *, DBT *, u_int32_t));
int (*put) __P((DB *, DB_TXN *, DBT *, DBT *, int)); int (*put) __P((DB *, DB_TXN *, DBT *, DBT *, u_int32_t));
int (*stat) __P((DB *, void *, void *(*)(size_t), int)); int (*stat) __P((DB *, void *, void *(*)(size_t), u_int32_t));
int (*sync) __P((DB *, int)); int (*sync) __P((DB *, u_int32_t));
#define DB_AM_DUP 0x000001 /* DB_DUP (internal). */ #define DB_AM_DUP 0x000001 /* DB_DUP (internal). */
#define DB_AM_INMEM 0x000002 /* In-memory; no sync on close. */ #define DB_AM_INMEM 0x000002 /* In-memory; no sync on close. */
@ -483,9 +490,9 @@ struct __dbc {
void *internal; /* Access method private. */ void *internal; /* Access method private. */
int (*c_close) __P((DBC *)); int (*c_close) __P((DBC *));
int (*c_del) __P((DBC *, int)); int (*c_del) __P((DBC *, u_int32_t));
int (*c_get) __P((DBC *, DBT *, DBT *, int)); int (*c_get) __P((DBC *, DBT *, DBT *, u_int32_t));
int (*c_put) __P((DBC *, DBT *, DBT *, int)); int (*c_put) __P((DBC *, DBT *, DBT *, u_int32_t));
}; };
/* Btree/recno statistics structure. */ /* Btree/recno statistics structure. */
@ -524,10 +531,11 @@ struct __db_bt_stat {
#if defined(__cplusplus) #if defined(__cplusplus)
extern "C" { extern "C" {
#endif #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_appexit __P((DB_ENV *));
int db_jump_set __P((void *, int)); 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)); int db_value_set __P((int, int));
char *db_version __P((int *, int *, int *)); char *db_version __P((int *, int *, int *));
#if defined(__cplusplus) #if defined(__cplusplus)
@ -575,6 +583,21 @@ typedef enum {
DB_LOCK_IWR /* Intent to read and write. */ DB_LOCK_IWR /* Intent to read and write. */
} db_lockmode_t; } 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. */ /* Lock request structure. */
struct __db_lockreq { struct __db_lockreq {
db_lockop_t op; /* Operation. */ db_lockop_t op; /* Operation. */
@ -596,19 +619,38 @@ extern const u_int8_t db_rw_conflicts[];
#define DB_LOCK_RIW_N 6 #define DB_LOCK_RIW_N 6
extern const u_int8_t db_riw_conflicts[]; 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) #if defined(__cplusplus)
extern "C" { extern "C" {
#endif #endif
int lock_close __P((DB_LOCKTAB *)); 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 *, 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_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_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_unlink __P((const char *, int, DB_ENV *));
int lock_vec __P((DB_LOCKTAB *, 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) #if defined(__cplusplus)
} }
#endif #endif
@ -651,19 +693,21 @@ struct __db_log_stat {
u_int32_t st_region_nowait; /* Region lock granted without wait. */ 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_file; /* Current log file number. */
u_int32_t st_cur_offset; /* Current log file offset. */ 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) #if defined(__cplusplus)
extern "C" { extern "C" {
#endif #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_close __P((DB_LOG *));
int log_compare __P((const DB_LSN *, const DB_LSN *)); int log_compare __P((const DB_LSN *, const DB_LSN *));
int log_file __P((DB_LOG *, const DB_LSN *, char *, size_t)); int log_file __P((DB_LOG *, const DB_LSN *, char *, size_t));
int log_flush __P((DB_LOG *, const DB_LSN *)); int log_flush __P((DB_LOG *, const DB_LSN *));
int log_get __P((DB_LOG *, DB_LSN *, DBT *, int)); int log_get __P((DB_LOG *, DB_LSN *, DBT *, u_int32_t));
int log_open __P((const char *, int, int, DB_ENV *, DB_LOG **)); int log_open __P((const char *, u_int32_t, int, DB_ENV *, DB_LOG **));
int log_put __P((DB_LOG *, DB_LSN *, const DBT *, int)); 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_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_stat __P((DB_LOG *, DB_LOG_STAT **, void *(*)(size_t)));
int log_unlink __P((const char *, int, DB_ENV *)); 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_page_trickle; /* Pages written by memp_trickle. */
u_int32_t st_region_wait; /* Region lock granted after wait. */ 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_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. */ /* Mpool file statistics structure. */
@ -724,13 +779,13 @@ extern "C" {
#endif #endif
int memp_close __P((DB_MPOOL *)); int memp_close __P((DB_MPOOL *));
int memp_fclose __P((DB_MPOOLFILE *)); 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 memp_fopen __P((DB_MPOOL *, const char *,
int, int, int, size_t, int, DBT *, u_int8_t *, DB_MPOOLFILE **)); u_int32_t, int, size_t, DB_MPOOL_FINFO *, DB_MPOOLFILE **));
int memp_fput __P((DB_MPOOLFILE *, void *, int)); int memp_fput __P((DB_MPOOLFILE *, void *, u_int32_t));
int memp_fset __P((DB_MPOOLFILE *, void *, int)); int memp_fset __P((DB_MPOOLFILE *, void *, u_int32_t));
int memp_fsync __P((DB_MPOOLFILE *)); 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 memp_register __P((DB_MPOOL *, int,
int (*)(db_pgno_t, void *, DBT *), int (*)(db_pgno_t, void *, DBT *),
int (*)(db_pgno_t, void *, DBT *))); int (*)(db_pgno_t, void *, DBT *)));
@ -765,16 +820,21 @@ struct __db_txn_active {
}; };
struct __db_txn_stat { struct __db_txn_stat {
DB_LSN st_last_ckp; /* lsn of the last checkpoint */ DB_LSN st_last_ckp; /* lsn of the last checkpoint */
DB_LSN st_pending_ckp; /* last checkpoint did not finish */ DB_LSN st_pending_ckp; /* last checkpoint did not finish */
time_t st_time_ckp; /* time of last checkpoint */ time_t st_time_ckp; /* time of last checkpoint */
u_int32_t st_last_txnid; /* last transaction id given out */ 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_maxtxns; /* maximum number of active txns */
u_int32_t st_naborts; /* number of aborted transactions */ u_int32_t st_naborts; /* number of aborted transactions */
u_int32_t st_nbegins; /* number of begun transactions */ u_int32_t st_nbegins; /* number of begun transactions */
u_int32_t st_ncommits; /* number of committed transactions */ u_int32_t st_ncommits; /* number of committed transactions */
u_int32_t st_nactive; /* number of active transactions */ u_int32_t st_nactive; /* number of active transactions */
DB_TXN_ACTIVE *st_txnarray; /* array 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) #if defined(__cplusplus)
@ -782,11 +842,11 @@ extern "C" {
#endif #endif
int txn_abort __P((DB_TXN *)); int txn_abort __P((DB_TXN *));
int txn_begin __P((DB_TXNMGR *, DB_TXN *, 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_commit __P((DB_TXN *));
int txn_close __P((DB_TXNMGR *)); int txn_close __P((DB_TXNMGR *));
u_int32_t txn_id __P((DB_TXN *)); 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_prepare __P((DB_TXN *));
int txn_stat __P((DB_TXNMGR *, DB_TXN_STAT **, void *(*)(size_t))); int txn_stat __P((DB_TXNMGR *, DB_TXN_STAT **, void *(*)(size_t)));
int txn_unlink __P((const char *, int, DB_ENV *)); 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" #define DBM_SUFFIX ".db"
#if defined(_XPG4_2)
typedef struct {
char *dptr;
size_t dsize;
} datum;
#else
typedef struct { typedef struct {
char *dptr; char *dptr;
int dsize; int dsize;
} datum; } datum;
#endif
/* /*
* Translate DBM calls into DB calls so that DB doesn't step on the * Translate DBM calls into DB calls so that DB doesn't step on the
@ -894,7 +961,7 @@ typedef enum {
typedef struct entry { typedef struct entry {
char *key; char *key;
void *data; char *data;
} ENTRY; } ENTRY;
/* /*
@ -909,7 +976,7 @@ typedef struct entry {
#if defined(__cplusplus) #if defined(__cplusplus)
extern "C" { extern "C" {
#endif #endif
int __db_hcreate __P((unsigned int)); int __db_hcreate __P((size_t));
void __db_hdestroy __P((void)); void __db_hdestroy __P((void));
ENTRY *__db_hsearch __P((ENTRY, ACTION)); ENTRY *__db_hsearch __P((ENTRY, ACTION));
#if defined(__cplusplus) #if defined(__cplusplus)

View File

@ -1,7 +1,7 @@
/*- /*-
* See the file LICENSE for redistribution information. * See the file LICENSE for redistribution information.
* *
* Copyright (c) 1996, 1997 * Copyright (c) 1996, 1997, 1998
* Sleepycat Software. All rights reserved. * Sleepycat Software. All rights reserved.
*/ */
/* /*
@ -44,20 +44,16 @@
#include "config.h" #include "config.h"
#ifndef lint #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 */ #endif /* not lint */
#ifndef NO_SYSTEM_INCLUDES #ifndef NO_SYSTEM_INCLUDES
#include <sys/types.h> #include <sys/types.h>
#include <sys/stat.h>
#include <errno.h> #include <errno.h>
#include <fcntl.h>
#include <stddef.h> #include <stddef.h>
#include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <unistd.h>
#endif #endif
#include "db_int.h" #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 "db_am.h"
#include "common_ext.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 *)); static int db_fd __P((DB *, int *));
/* /*
@ -99,7 +95,8 @@ int
db_open(fname, type, flags, mode, dbenv, dbinfo, dbpp) db_open(fname, type, flags, mode, dbenv, dbinfo, dbpp)
const char *fname; const char *fname;
DBTYPE type; DBTYPE type;
int flags, mode; u_int32_t flags;
int mode;
DB_ENV *dbenv; DB_ENV *dbenv;
DB_INFO *dbinfo; DB_INFO *dbinfo;
DB **dbpp; DB **dbpp;
@ -108,6 +105,7 @@ db_open(fname, type, flags, mode, dbenv, dbinfo, dbpp)
DB *dbp; DB *dbp;
DBT pgcookie; DBT pgcookie;
DB_ENV *envp, t_dbenv; DB_ENV *envp, t_dbenv;
DB_MPOOL_FINFO finfo;
DB_PGINFO pginfo; DB_PGINFO pginfo;
HASHHDR *hashm; HASHHDR *hashm;
size_t cachesize; 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) if ((ret = __db_fchk(dbenv, "db_open", flags, OKFLAGS)) != 0)
return (ret); return (ret);
if (dbenv != NULL && if (dbenv != NULL) {
LF_ISSET(DB_THREAD) && !F_ISSET(dbenv, DB_ENV_THREAD)) { /*
__db_err(dbenv, "environment not created using DB_THREAD"); * You can't specify threads during the db_open() if the
return (EINVAL); * 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. */ /* Initialize for error return. */
@ -203,7 +217,7 @@ db_open(fname, type, flags, mode, dbenv, dbinfo, dbpp)
/* Fill in the default file mode. */ /* Fill in the default file mode. */
if (mode == 0) 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. */ /* Check if the user wants us to swap byte order. */
if (dbinfo != NULL) if (dbinfo != NULL)
@ -230,7 +244,7 @@ db_open(fname, type, flags, mode, dbenv, dbinfo, dbpp)
if (fname != NULL && fname[0] != '\0') { if (fname != NULL && fname[0] != '\0') {
/* Get the real file name. */ /* Get the real file name. */
if ((ret = __db_appname(dbenv, 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; goto err;
/* /*
@ -454,22 +468,6 @@ empty: /*
goto einval; goto einval;
} }
/*
* 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, * If no mpool supplied by the application, attach to a local,
* created buffer pool. * created buffer pool.
@ -499,10 +497,28 @@ empty: /*
envp = dbenv; envp = dbenv;
restore = 1; 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; envp->mp_size = cachesize;
if ((ret = memp_open(NULL, DB_CREATE | DB_MPOOL_PRIVATE | if ((ret = memp_open(NULL, DB_CREATE | DB_MPOOL_PRIVATE |
(F_ISSET(dbp, DB_AM_THREAD) ? DB_THREAD : 0), (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; goto err;
if (restore) if (restore)
*dbenv = t_dbenv; *dbenv = t_dbenv;
@ -566,9 +582,18 @@ empty: /*
pgcookie.data = &pginfo; pgcookie.data = &pginfo;
pgcookie.size = sizeof(DB_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, * Set up additional memp_fopen information.
0, &pgcookie, dbp->lock.fileid, &dbp->mpf)) != 0) */
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; goto err;
/* /*
@ -673,7 +698,7 @@ err: /* Close the file descriptor. */
static int static int
db_close(dbp, flags) db_close(dbp, flags)
DB *dbp; DB *dbp;
int flags; u_int32_t flags;
{ {
DBC *dbc; DBC *dbc;
DB *tdbp; DB *tdbp;
@ -734,7 +759,7 @@ db_close(dbp, flags)
} }
/* Sync the memory pool. */ /* 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) t_ret != DB_INCOMPLETE && ret == 0)
ret = t_ret; ret = t_ret;
@ -796,18 +821,11 @@ db_fd(dbp, fdp)
DB *dbp; DB *dbp;
int *fdp; int *fdp;
{ {
/* In-memory database can't have a file descriptor. */
if (F_ISSET(dbp, DB_AM_INMEM))
return (ENOENT);
/* /*
* XXX * XXX
* Truly spectacular layering violation. As we don't open the * Truly spectacular layering violation.
* underlying file until we need it, it may not be initialized.
*/ */
if ((*fdp = dbp->mpf->fd) == -1) return (__mp_xxx_fd(dbp->mpf, fdp));
return (ENOENT);
return (0);
} }
/* /*
@ -821,6 +839,11 @@ __db_pgerr(dbp, pgno)
DB *dbp; DB *dbp;
db_pgno_t pgno; db_pgno_t pgno;
{ {
/*
* Three things are certain:
* Death, taxes, and lost data.
* Guess which has occurred.
*/
__db_err(dbp->dbenv, __db_err(dbp->dbenv,
"unable to create/retrieve page %lu", (u_long)pgno); "unable to create/retrieve page %lu", (u_long)pgno);
return (__db_panic(dbp)); return (__db_panic(dbp));

View File

@ -1,11 +1,11 @@
/*- /*-
* See the file LICENSE for redistribution information. * See the file LICENSE for redistribution information.
* *
* Copyright (c) 1996, 1997 * Copyright (c) 1996, 1997, 1998
* Sleepycat Software. All rights reserved. * 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 PREFIX db
@ -153,4 +153,7 @@ END
* noop -- do nothing, but get an LSN. * noop -- do nothing, but get an LSN.
*/ */
BEGIN noop BEGIN noop
ARG fileid u_int32_t lu
ARG pgno db_pgno_t lu
POINTER prevlsn DB_LSN * lu
END END

View File

@ -14,8 +14,6 @@
#include "db_page.h" #include "db_page.h"
#include "db_dispatch.h" #include "db_dispatch.h"
#include "db_am.h" #include "db_am.h"
#include "common_ext.h"
/* /*
* PUBLIC: int __db_addrem_log * PUBLIC: int __db_addrem_log
* PUBLIC: __P((DB_LOG *, DB_TXN *, DB_LSN *, u_int32_t, * 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 else
memset(bp, 0, sizeof(*pagelsn)); memset(bp, 0, sizeof(*pagelsn));
bp += sizeof(*pagelsn); bp += sizeof(*pagelsn);
#ifdef DEBUG #ifdef DIAGNOSTIC
if ((u_int32_t)(bp - (u_int8_t *)logrec.data) != logrec.size) if ((u_int32_t)(bp - (u_int8_t *)logrec.data) != logrec.size)
fprintf(stderr, "Error in log record length"); fprintf(stderr, "Error in log record length");
#endif #endif
@ -123,22 +121,23 @@ int __db_addrem_log(logp, txnid, ret_lsnp, flags,
* PUBLIC: __P((DB_LOG *, DBT *, DB_LSN *, int, void *)); * PUBLIC: __P((DB_LOG *, DBT *, DB_LSN *, int, void *));
*/ */
int int
__db_addrem_print(notused1, dbtp, lsnp, notused3, notused4) __db_addrem_print(notused1, dbtp, lsnp, notused2, notused3)
DB_LOG *notused1; DB_LOG *notused1;
DBT *dbtp; DBT *dbtp;
DB_LSN *lsnp; DB_LSN *lsnp;
int notused3; int notused2;
void *notused4; void *notused3;
{ {
__db_addrem_args *argp; __db_addrem_args *argp;
u_int32_t i; u_int32_t i;
int c, ret; u_int ch;
int ret;
i = 0; i = 0;
c = 0; ch = 0;
notused1 = NULL; notused1 = NULL;
notused3 = 0; notused2 = 0;
notused4 = NULL; notused3 = NULL;
if ((ret = __db_addrem_read(dbtp->data, &argp)) != 0) if ((ret = __db_addrem_read(dbtp->data, &argp)) != 0)
return (ret); return (ret);
@ -156,20 +155,20 @@ __db_addrem_print(notused1, dbtp, lsnp, notused3, notused4)
printf("\tnbytes: %lu\n", (u_long)argp->nbytes); printf("\tnbytes: %lu\n", (u_long)argp->nbytes);
printf("\thdr: "); printf("\thdr: ");
for (i = 0; i < argp->hdr.size; i++) { for (i = 0; i < argp->hdr.size; i++) {
c = ((char *)argp->hdr.data)[i]; ch = ((u_int8_t *)argp->hdr.data)[i];
if (isprint(c) || c == 0xa) if (isprint(ch) || ch == 0xa)
putchar(c); putchar(ch);
else else
printf("%#x ", c); printf("%#x ", ch);
} }
printf("\n"); printf("\n");
printf("\tdbt: "); printf("\tdbt: ");
for (i = 0; i < argp->dbt.size; i++) { for (i = 0; i < argp->dbt.size; i++) {
c = ((char *)argp->dbt.data)[i]; ch = ((u_int8_t *)argp->dbt.data)[i];
if (isprint(c) || c == 0xa) if (isprint(ch) || ch == 0xa)
putchar(c); putchar(ch);
else else
printf("%#x ", c); printf("%#x ", ch);
} }
printf("\n"); printf("\n");
printf("\tpagelsn: [%lu][%lu]\n", printf("\tpagelsn: [%lu][%lu]\n",
@ -296,7 +295,7 @@ int __db_split_log(logp, txnid, ret_lsnp, flags,
else else
memset(bp, 0, sizeof(*pagelsn)); memset(bp, 0, sizeof(*pagelsn));
bp += sizeof(*pagelsn); bp += sizeof(*pagelsn);
#ifdef DEBUG #ifdef DIAGNOSTIC
if ((u_int32_t)(bp - (u_int8_t *)logrec.data) != logrec.size) if ((u_int32_t)(bp - (u_int8_t *)logrec.data) != logrec.size)
fprintf(stderr, "Error in log record length"); fprintf(stderr, "Error in log record length");
#endif #endif
@ -312,22 +311,23 @@ int __db_split_log(logp, txnid, ret_lsnp, flags,
* PUBLIC: __P((DB_LOG *, DBT *, DB_LSN *, int, void *)); * PUBLIC: __P((DB_LOG *, DBT *, DB_LSN *, int, void *));
*/ */
int int
__db_split_print(notused1, dbtp, lsnp, notused3, notused4) __db_split_print(notused1, dbtp, lsnp, notused2, notused3)
DB_LOG *notused1; DB_LOG *notused1;
DBT *dbtp; DBT *dbtp;
DB_LSN *lsnp; DB_LSN *lsnp;
int notused3; int notused2;
void *notused4; void *notused3;
{ {
__db_split_args *argp; __db_split_args *argp;
u_int32_t i; u_int32_t i;
int c, ret; u_int ch;
int ret;
i = 0; i = 0;
c = 0; ch = 0;
notused1 = NULL; notused1 = NULL;
notused3 = 0; notused2 = 0;
notused4 = NULL; notused3 = NULL;
if ((ret = __db_split_read(dbtp->data, &argp)) != 0) if ((ret = __db_split_read(dbtp->data, &argp)) != 0)
return (ret); return (ret);
@ -343,11 +343,11 @@ __db_split_print(notused1, dbtp, lsnp, notused3, notused4)
printf("\tpgno: %lu\n", (u_long)argp->pgno); printf("\tpgno: %lu\n", (u_long)argp->pgno);
printf("\tpageimage: "); printf("\tpageimage: ");
for (i = 0; i < argp->pageimage.size; i++) { for (i = 0; i < argp->pageimage.size; i++) {
c = ((char *)argp->pageimage.data)[i]; ch = ((u_int8_t *)argp->pageimage.data)[i];
if (isprint(c) || c == 0xa) if (isprint(ch) || ch == 0xa)
putchar(c); putchar(ch);
else else
printf("%#x ", c); printf("%#x ", ch);
} }
printf("\n"); printf("\n");
printf("\tpagelsn: [%lu][%lu]\n", printf("\tpagelsn: [%lu][%lu]\n",
@ -490,7 +490,7 @@ int __db_big_log(logp, txnid, ret_lsnp, flags,
else else
memset(bp, 0, sizeof(*nextlsn)); memset(bp, 0, sizeof(*nextlsn));
bp += sizeof(*nextlsn); bp += sizeof(*nextlsn);
#ifdef DEBUG #ifdef DIAGNOSTIC
if ((u_int32_t)(bp - (u_int8_t *)logrec.data) != logrec.size) if ((u_int32_t)(bp - (u_int8_t *)logrec.data) != logrec.size)
fprintf(stderr, "Error in log record length"); fprintf(stderr, "Error in log record length");
#endif #endif
@ -506,22 +506,23 @@ int __db_big_log(logp, txnid, ret_lsnp, flags,
* PUBLIC: __P((DB_LOG *, DBT *, DB_LSN *, int, void *)); * PUBLIC: __P((DB_LOG *, DBT *, DB_LSN *, int, void *));
*/ */
int int
__db_big_print(notused1, dbtp, lsnp, notused3, notused4) __db_big_print(notused1, dbtp, lsnp, notused2, notused3)
DB_LOG *notused1; DB_LOG *notused1;
DBT *dbtp; DBT *dbtp;
DB_LSN *lsnp; DB_LSN *lsnp;
int notused3; int notused2;
void *notused4; void *notused3;
{ {
__db_big_args *argp; __db_big_args *argp;
u_int32_t i; u_int32_t i;
int c, ret; u_int ch;
int ret;
i = 0; i = 0;
c = 0; ch = 0;
notused1 = NULL; notused1 = NULL;
notused3 = 0; notused2 = 0;
notused4 = NULL; notused3 = NULL;
if ((ret = __db_big_read(dbtp->data, &argp)) != 0) if ((ret = __db_big_read(dbtp->data, &argp)) != 0)
return (ret); 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("\tnext_pgno: %lu\n", (u_long)argp->next_pgno);
printf("\tdbt: "); printf("\tdbt: ");
for (i = 0; i < argp->dbt.size; i++) { for (i = 0; i < argp->dbt.size; i++) {
c = ((char *)argp->dbt.data)[i]; ch = ((u_int8_t *)argp->dbt.data)[i];
if (isprint(c) || c == 0xa) if (isprint(ch) || ch == 0xa)
putchar(c); putchar(ch);
else else
printf("%#x ", c); printf("%#x ", ch);
} }
printf("\n"); printf("\n");
printf("\tpagelsn: [%lu][%lu]\n", printf("\tpagelsn: [%lu][%lu]\n",
@ -660,7 +661,7 @@ int __db_ovref_log(logp, txnid, ret_lsnp, flags,
else else
memset(bp, 0, sizeof(*lsn)); memset(bp, 0, sizeof(*lsn));
bp += sizeof(*lsn); bp += sizeof(*lsn);
#ifdef DEBUG #ifdef DIAGNOSTIC
if ((u_int32_t)(bp - (u_int8_t *)logrec.data) != logrec.size) if ((u_int32_t)(bp - (u_int8_t *)logrec.data) != logrec.size)
fprintf(stderr, "Error in log record length"); fprintf(stderr, "Error in log record length");
#endif #endif
@ -676,22 +677,23 @@ int __db_ovref_log(logp, txnid, ret_lsnp, flags,
* PUBLIC: __P((DB_LOG *, DBT *, DB_LSN *, int, void *)); * PUBLIC: __P((DB_LOG *, DBT *, DB_LSN *, int, void *));
*/ */
int int
__db_ovref_print(notused1, dbtp, lsnp, notused3, notused4) __db_ovref_print(notused1, dbtp, lsnp, notused2, notused3)
DB_LOG *notused1; DB_LOG *notused1;
DBT *dbtp; DBT *dbtp;
DB_LSN *lsnp; DB_LSN *lsnp;
int notused3; int notused2;
void *notused4; void *notused3;
{ {
__db_ovref_args *argp; __db_ovref_args *argp;
u_int32_t i; u_int32_t i;
int c, ret; u_int ch;
int ret;
i = 0; i = 0;
c = 0; ch = 0;
notused1 = NULL; notused1 = NULL;
notused3 = 0; notused2 = 0;
notused4 = NULL; notused3 = NULL;
if ((ret = __db_ovref_read(dbtp->data, &argp)) != 0) if ((ret = __db_ovref_read(dbtp->data, &argp)) != 0)
return (ret); return (ret);
@ -823,7 +825,7 @@ int __db_relink_log(logp, txnid, ret_lsnp, flags,
else else
memset(bp, 0, sizeof(*lsn_next)); memset(bp, 0, sizeof(*lsn_next));
bp += sizeof(*lsn_next); bp += sizeof(*lsn_next);
#ifdef DEBUG #ifdef DIAGNOSTIC
if ((u_int32_t)(bp - (u_int8_t *)logrec.data) != logrec.size) if ((u_int32_t)(bp - (u_int8_t *)logrec.data) != logrec.size)
fprintf(stderr, "Error in log record length"); fprintf(stderr, "Error in log record length");
#endif #endif
@ -839,22 +841,23 @@ int __db_relink_log(logp, txnid, ret_lsnp, flags,
* PUBLIC: __P((DB_LOG *, DBT *, DB_LSN *, int, void *)); * PUBLIC: __P((DB_LOG *, DBT *, DB_LSN *, int, void *));
*/ */
int int
__db_relink_print(notused1, dbtp, lsnp, notused3, notused4) __db_relink_print(notused1, dbtp, lsnp, notused2, notused3)
DB_LOG *notused1; DB_LOG *notused1;
DBT *dbtp; DBT *dbtp;
DB_LSN *lsnp; DB_LSN *lsnp;
int notused3; int notused2;
void *notused4; void *notused3;
{ {
__db_relink_args *argp; __db_relink_args *argp;
u_int32_t i; u_int32_t i;
int c, ret; u_int ch;
int ret;
i = 0; i = 0;
c = 0; ch = 0;
notused1 = NULL; notused1 = NULL;
notused3 = 0; notused2 = 0;
notused4 = NULL; notused3 = NULL;
if ((ret = __db_relink_read(dbtp->data, &argp)) != 0) if ((ret = __db_relink_read(dbtp->data, &argp)) != 0)
return (ret); return (ret);
@ -985,7 +988,7 @@ int __db_addpage_log(logp, txnid, ret_lsnp, flags,
else else
memset(bp, 0, sizeof(*nextlsn)); memset(bp, 0, sizeof(*nextlsn));
bp += sizeof(*nextlsn); bp += sizeof(*nextlsn);
#ifdef DEBUG #ifdef DIAGNOSTIC
if ((u_int32_t)(bp - (u_int8_t *)logrec.data) != logrec.size) if ((u_int32_t)(bp - (u_int8_t *)logrec.data) != logrec.size)
fprintf(stderr, "Error in log record length"); fprintf(stderr, "Error in log record length");
#endif #endif
@ -1001,22 +1004,23 @@ int __db_addpage_log(logp, txnid, ret_lsnp, flags,
* PUBLIC: __P((DB_LOG *, DBT *, DB_LSN *, int, void *)); * PUBLIC: __P((DB_LOG *, DBT *, DB_LSN *, int, void *));
*/ */
int int
__db_addpage_print(notused1, dbtp, lsnp, notused3, notused4) __db_addpage_print(notused1, dbtp, lsnp, notused2, notused3)
DB_LOG *notused1; DB_LOG *notused1;
DBT *dbtp; DBT *dbtp;
DB_LSN *lsnp; DB_LSN *lsnp;
int notused3; int notused2;
void *notused4; void *notused3;
{ {
__db_addpage_args *argp; __db_addpage_args *argp;
u_int32_t i; u_int32_t i;
int c, ret; u_int ch;
int ret;
i = 0; i = 0;
c = 0; ch = 0;
notused1 = NULL; notused1 = NULL;
notused3 = 0; notused2 = 0;
notused4 = NULL; notused3 = NULL;
if ((ret = __db_addpage_read(dbtp->data, &argp)) != 0) if ((ret = __db_addpage_read(dbtp->data, &argp)) != 0)
return (ret); return (ret);
@ -1159,7 +1163,7 @@ int __db_debug_log(logp, txnid, ret_lsnp, flags,
} }
memcpy(bp, &arg_flags, sizeof(arg_flags)); memcpy(bp, &arg_flags, sizeof(arg_flags));
bp += sizeof(arg_flags); bp += sizeof(arg_flags);
#ifdef DEBUG #ifdef DIAGNOSTIC
if ((u_int32_t)(bp - (u_int8_t *)logrec.data) != logrec.size) if ((u_int32_t)(bp - (u_int8_t *)logrec.data) != logrec.size)
fprintf(stderr, "Error in log record length"); fprintf(stderr, "Error in log record length");
#endif #endif
@ -1175,22 +1179,23 @@ int __db_debug_log(logp, txnid, ret_lsnp, flags,
* PUBLIC: __P((DB_LOG *, DBT *, DB_LSN *, int, void *)); * PUBLIC: __P((DB_LOG *, DBT *, DB_LSN *, int, void *));
*/ */
int int
__db_debug_print(notused1, dbtp, lsnp, notused3, notused4) __db_debug_print(notused1, dbtp, lsnp, notused2, notused3)
DB_LOG *notused1; DB_LOG *notused1;
DBT *dbtp; DBT *dbtp;
DB_LSN *lsnp; DB_LSN *lsnp;
int notused3; int notused2;
void *notused4; void *notused3;
{ {
__db_debug_args *argp; __db_debug_args *argp;
u_int32_t i; u_int32_t i;
int c, ret; u_int ch;
int ret;
i = 0; i = 0;
c = 0; ch = 0;
notused1 = NULL; notused1 = NULL;
notused3 = 0; notused2 = 0;
notused4 = NULL; notused3 = NULL;
if ((ret = __db_debug_read(dbtp->data, &argp)) != 0) if ((ret = __db_debug_read(dbtp->data, &argp)) != 0)
return (ret); return (ret);
@ -1203,30 +1208,30 @@ __db_debug_print(notused1, dbtp, lsnp, notused3, notused4)
(u_long)argp->prev_lsn.offset); (u_long)argp->prev_lsn.offset);
printf("\top: "); printf("\top: ");
for (i = 0; i < argp->op.size; i++) { for (i = 0; i < argp->op.size; i++) {
c = ((char *)argp->op.data)[i]; ch = ((u_int8_t *)argp->op.data)[i];
if (isprint(c) || c == 0xa) if (isprint(ch) || ch == 0xa)
putchar(c); putchar(ch);
else else
printf("%#x ", c); printf("%#x ", ch);
} }
printf("\n"); printf("\n");
printf("\tfileid: %lu\n", (u_long)argp->fileid); printf("\tfileid: %lu\n", (u_long)argp->fileid);
printf("\tkey: "); printf("\tkey: ");
for (i = 0; i < argp->key.size; i++) { for (i = 0; i < argp->key.size; i++) {
c = ((char *)argp->key.data)[i]; ch = ((u_int8_t *)argp->key.data)[i];
if (isprint(c) || c == 0xa) if (isprint(ch) || ch == 0xa)
putchar(c); putchar(ch);
else else
printf("%#x ", c); printf("%#x ", ch);
} }
printf("\n"); printf("\n");
printf("\tdata: "); printf("\tdata: ");
for (i = 0; i < argp->data.size; i++) { for (i = 0; i < argp->data.size; i++) {
c = ((char *)argp->data.data)[i]; ch = ((u_int8_t *)argp->data.data)[i];
if (isprint(c) || c == 0xa) if (isprint(ch) || ch == 0xa)
putchar(c); putchar(ch);
else else
printf("%#x ", c); printf("%#x ", ch);
} }
printf("\n"); printf("\n");
printf("\targ_flags: %lu\n", (u_long)argp->arg_flags); 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: 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_LOG *logp;
DB_TXN *txnid; DB_TXN *txnid;
DB_LSN *ret_lsnp; DB_LSN *ret_lsnp;
u_int32_t flags; u_int32_t flags;
u_int32_t fileid;
db_pgno_t pgno;
DB_LSN * prevlsn;
{ {
DBT logrec; DBT logrec;
DB_LSN *lsnp, null_lsn; DB_LSN *lsnp, null_lsn;
@ -1302,7 +1312,10 @@ int __db_noop_log(logp, txnid, ret_lsnp, flags)
lsnp = &null_lsn; lsnp = &null_lsn;
} else } else
lsnp = &txnid->last_lsn; 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) if ((logrec.data = (void *)__db_malloc(logrec.size)) == NULL)
return (ENOMEM); return (ENOMEM);
@ -1313,7 +1326,16 @@ int __db_noop_log(logp, txnid, ret_lsnp, flags)
bp += sizeof(txn_num); bp += sizeof(txn_num);
memcpy(bp, lsnp, sizeof(DB_LSN)); memcpy(bp, lsnp, sizeof(DB_LSN));
bp += 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) if ((u_int32_t)(bp - (u_int8_t *)logrec.data) != logrec.size)
fprintf(stderr, "Error in log record length"); fprintf(stderr, "Error in log record length");
#endif #endif
@ -1329,22 +1351,23 @@ int __db_noop_log(logp, txnid, ret_lsnp, flags)
* PUBLIC: __P((DB_LOG *, DBT *, DB_LSN *, int, void *)); * PUBLIC: __P((DB_LOG *, DBT *, DB_LSN *, int, void *));
*/ */
int int
__db_noop_print(notused1, dbtp, lsnp, notused3, notused4) __db_noop_print(notused1, dbtp, lsnp, notused2, notused3)
DB_LOG *notused1; DB_LOG *notused1;
DBT *dbtp; DBT *dbtp;
DB_LSN *lsnp; DB_LSN *lsnp;
int notused3; int notused2;
void *notused4; void *notused3;
{ {
__db_noop_args *argp; __db_noop_args *argp;
u_int32_t i; u_int32_t i;
int c, ret; u_int ch;
int ret;
i = 0; i = 0;
c = 0; ch = 0;
notused1 = NULL; notused1 = NULL;
notused3 = 0; notused2 = 0;
notused4 = NULL; notused3 = NULL;
if ((ret = __db_noop_read(dbtp->data, &argp)) != 0) if ((ret = __db_noop_read(dbtp->data, &argp)) != 0)
return (ret); return (ret);
@ -1355,6 +1378,10 @@ __db_noop_print(notused1, dbtp, lsnp, notused3, notused4)
(u_long)argp->txnid->txnid, (u_long)argp->txnid->txnid,
(u_long)argp->prev_lsn.file, (u_long)argp->prev_lsn.file,
(u_long)argp->prev_lsn.offset); (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"); printf("\n");
__db_free(argp); __db_free(argp);
return (0); return (0);
@ -1383,6 +1410,12 @@ __db_noop_read(recbuf, argpp)
bp += sizeof(argp->txnid->txnid); bp += sizeof(argp->txnid->txnid);
memcpy(&argp->prev_lsn, bp, sizeof(DB_LSN)); memcpy(&argp->prev_lsn, bp, sizeof(DB_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; *argpp = argp;
return (0); return (0);
} }

View File

@ -1,7 +1,7 @@
/*- /*-
* See the file LICENSE for redistribution information. * See the file LICENSE for redistribution information.
* *
* Copyright (c) 1996, 1997 * Copyright (c) 1996, 1997, 1998
* Sleepycat Software. All rights reserved. * Sleepycat Software. All rights reserved.
*/ */
/* /*
@ -44,7 +44,7 @@
#include "config.h" #include "config.h"
#ifndef lint #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 */ #endif /* not lint */
#ifndef NO_SYSTEM_INCLUDES #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) if (!pgin)
for (i = 0; i < NUM_ENT(h); i++) for (i = 0; i < NUM_ENT(h); i++)
M_16_SWAP(h->inp[i]); M_16_SWAP(h->inp[i]);
@ -179,8 +186,8 @@ __db_convert(pg, pp, pagesize, pgin)
case B_DUPLICATE: case B_DUPLICATE:
case B_OVERFLOW: case B_OVERFLOW:
bo = (BOVERFLOW *)bk; bo = (BOVERFLOW *)bk;
M_32_SWAP(bo->tlen);
M_32_SWAP(bo->pgno); M_32_SWAP(bo->pgno);
M_32_SWAP(bo->tlen);
break; break;
} }
@ -194,17 +201,18 @@ __db_convert(pg, pp, pagesize, pgin)
M_16_SWAP(h->inp[i]); M_16_SWAP(h->inp[i]);
bi = GET_BINTERNAL(h, 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)) { switch (B_TYPE(bi->type)) {
case B_KEYDATA: case B_KEYDATA:
M_16_SWAP(bi->len);
M_32_SWAP(bi->pgno);
M_32_SWAP(bi->nrecs);
break; break;
case B_DUPLICATE: case B_DUPLICATE:
case B_OVERFLOW: case B_OVERFLOW:
bo = (BOVERFLOW *)bi; bo = (BOVERFLOW *)bi->data;
M_32_SWAP(bo->tlen);
M_32_SWAP(bo->pgno); M_32_SWAP(bo->pgno);
M_32_SWAP(bo->tlen);
break; break;
} }
@ -224,6 +232,7 @@ __db_convert(pg, pp, pagesize, pgin)
if (!pgin) if (!pgin)
M_16_SWAP(h->inp[i]); M_16_SWAP(h->inp[i]);
} }
break;
case P_OVERFLOW: case P_OVERFLOW:
case P_INVALID: case P_INVALID:
/* Nothing to do. */ /* Nothing to do. */

View File

@ -1,7 +1,7 @@
/*- /*-
* See the file LICENSE for redistribution information. * See the file LICENSE for redistribution information.
* *
* Copyright (c) 1996, 1997 * Copyright (c) 1996, 1997, 1998
* Sleepycat Software. All rights reserved. * Sleepycat Software. All rights reserved.
*/ */
/* /*
@ -43,14 +43,13 @@
#include "config.h" #include "config.h"
#ifndef lint #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 */ #endif /* not lint */
#ifndef NO_SYSTEM_INCLUDES #ifndef NO_SYSTEM_INCLUDES
#include <sys/types.h> #include <sys/types.h>
#include <errno.h> #include <errno.h>
#include <fcntl.h>
#include <stddef.h> #include <stddef.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.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 "db_am.h"
#include "common_ext.h" #include "common_ext.h"
#include "log_auto.h" #include "log_auto.h"
#include "txn_auto.h"
/* /*
* Data structures to manage the DB dispatch table. The dispatch table * 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 * seen it, then we call the appropriate recovery routine
* in "abort mode". * in "abort mode".
*/ */
if (rectype == DB_log_register || if (rectype == DB_log_register || rectype == DB_txn_ckp ||
__db_txnlist_find(info, txnid) == DB_NOTFOUND) __db_txnlist_find(info, txnid) == DB_NOTFOUND)
return ((dispatch_table[rectype])(logp, return ((dispatch_table[rectype])(logp,
db, lsnp, TXN_UNDO, info)); 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, * In the forward pass, if we haven't seen the transaction,
* do nothing, else recovery it. * 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) __db_txnlist_find(info, txnid) != DB_NOTFOUND)
return ((dispatch_table[rectype])(logp, return ((dispatch_table[rectype])(logp,
db, lsnp, TXN_REDO, info)); db, lsnp, TXN_REDO, info));
@ -188,14 +188,14 @@ int
__db_txnlist_init(retp) __db_txnlist_init(retp)
void *retp; void *retp;
{ {
__db_txnhead *headp; DB_TXNHEAD *headp;
if ((headp = (struct __db_txnhead *) if ((headp = (DB_TXNHEAD *)__db_malloc(sizeof(DB_TXNHEAD))) == NULL)
__db_malloc(sizeof(struct __db_txnhead))) == NULL)
return (ENOMEM); return (ENOMEM);
LIST_INIT(&headp->head); LIST_INIT(&headp->head);
headp->maxid = 0; headp->maxid = 0;
headp->generation = 1;
*(void **)retp = headp; *(void **)retp = headp;
return (0); return (0);
@ -212,25 +212,26 @@ __db_txnlist_add(listp, txnid)
void *listp; void *listp;
u_int32_t txnid; u_int32_t txnid;
{ {
__db_txnhead *hp; DB_TXNHEAD *hp;
__db_txnlist *elp; 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); return (ENOMEM);
elp->txnid = txnid; elp->txnid = txnid;
hp = (struct __db_txnhead *)listp; hp = (DB_TXNHEAD *)listp;
LIST_INSERT_HEAD(&hp->head, elp, links); LIST_INSERT_HEAD(&hp->head, elp, links);
if (txnid > hp->maxid) if (txnid > hp->maxid)
hp->maxid = txnid; hp->maxid = txnid;
elp->generation = hp->generation;
return (0); return (0);
} }
/* /*
* __db_txnlist_find -- * __db_txnlist_find --
* Checks to see if txnid is in the txnid list, returns 1 if found, * Checks to see if a txnid with the current generation is in the
* 0 if not found. * txnid list.
* *
* PUBLIC: int __db_txnlist_find __P((void *, u_int32_t)); * PUBLIC: int __db_txnlist_find __P((void *, u_int32_t));
*/ */
@ -239,24 +240,65 @@ __db_txnlist_find(listp, txnid)
void *listp; void *listp;
u_int32_t txnid; u_int32_t txnid;
{ {
__db_txnhead *hp; DB_TXNHEAD *hp;
__db_txnlist *p; DB_TXNLIST *p;
if ((hp = (struct __db_txnhead *)listp) == NULL) if ((hp = (DB_TXNHEAD *)listp) == NULL)
return (DB_NOTFOUND); 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) 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 (0);
return (DB_NOTFOUND); return (DB_NOTFOUND);
} }
/*
* __db_txnlist_end --
* Discard transaction linked list.
*
* PUBLIC: void __db_txnlist_end __P((void *));
*/
void
__db_txnlist_end(listp)
void *listp;
{
DB_TXNHEAD *hp;
DB_TXNLIST *p;
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 #ifdef DEBUG
/* /*
* __db_txnlist_print -- * __db_txnlist_print --
@ -268,33 +310,14 @@ void
__db_txnlist_print(listp) __db_txnlist_print(listp)
void *listp; void *listp;
{ {
__db_txnhead *hp; DB_TXNHEAD *hp;
__db_txnlist *p; DB_TXNLIST *p;
hp = (struct __db_txnhead *)listp; hp = (DB_TXNHEAD *)listp;
printf("Maxid: %lu\n", (u_long)hp->maxid); 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) for (p = hp->head.lh_first; p != NULL; p = p->links.le_next)
printf("TXNID: %lu\n", (u_long)p->txnid); printf("TXNID: %lu(%lu)\n", (u_long)p->txnid,
(u_long)p->generation);
} }
#endif #endif
/*
* __db_txnlist_end --
* Discard transaction linked list.
*
* PUBLIC: void __db_txnlist_end __P((void *));
*/
void
__db_txnlist_end(listp)
void *listp;
{
__db_txnhead *hp;
__db_txnlist *p;
hp = (struct __db_txnhead *)listp;
while ((p = LIST_FIRST(&hp->head)) != LIST_END(&hp->head)) {
LIST_REMOVE(p, links);
__db_free(p);
}
__db_free(listp);
}

View File

@ -1,35 +1,27 @@
/*- /*-
* See the file LICENSE for redistribution information. * See the file LICENSE for redistribution information.
* *
* Copyright (c) 1996, 1997 * Copyright (c) 1996, 1997, 1998
* Sleepycat Software. All rights reserved. * Sleepycat Software. All rights reserved.
*/ */
#include "config.h" #include "config.h"
#ifndef lint #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 */ #endif /* not lint */
#ifndef NO_SYSTEM_INCLUDES #ifndef NO_SYSTEM_INCLUDES
#include <sys/types.h> #include <sys/types.h>
#include <sys/stat.h>
#include <errno.h> #include <errno.h>
#include <fcntl.h>
#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h> #include <string.h>
#include <unistd.h>
#endif #endif
#include "db_int.h" #include "db_int.h"
#include "db_page.h" #include "db_page.h"
#include "db_swap.h"
#include "btree.h" #include "btree.h"
#include "db_am.h" #include "db_am.h"
#include "common_ext.h"
static int __db_addpage __P((DB *, static int __db_addpage __P((DB *,
PAGE **, db_indx_t *, int (*)(DB *, u_int32_t, PAGE **))); 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; PAGE *h, *np, *tp;
BKEYDATA *bk; BKEYDATA *bk;
DBT page_dbt; DBT page_dbt;
db_indx_t indx, nindex, oindex, sum; db_indx_t halfbytes, i, indx, lastsum, nindex, oindex, s, sum;
db_indx_t halfbytes, i, lastsum; int did_indx, ret;
int did_indx, ret, s;
h = *hp; h = *hp;
indx = *indxp; indx = *indxp;
@ -219,7 +210,7 @@ __db_dsplit(dbp, hp, indxp, size, newfunc)
/* Create a temporary page to do compaction onto. */ /* Create a temporary page to do compaction onto. */
if ((tp = (PAGE *)__db_malloc(dbp->pgsize)) == NULL) if ((tp = (PAGE *)__db_malloc(dbp->pgsize)) == NULL)
return (ENOMEM); return (ENOMEM);
#ifdef DEBUG #ifdef DIAGNOSTIC
memset(tp, 0xff, dbp->pgsize); memset(tp, 0xff, dbp->pgsize);
#endif #endif
/* Create new page for the split. */ /* 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++) { for (sum = 0, lastsum = 0, i = 0; i < NUM_ENT(h); i++) {
if (i == indx) { if (i == indx) {
sum += size; sum += size;
did_indx = 1;
if (lastsum < halfbytes && sum >= halfbytes) { if (lastsum < halfbytes && sum >= halfbytes) {
/* We've crossed the halfway point. */ /* We've crossed the halfway point. */
if ((db_indx_t)(halfbytes - lastsum) < if ((db_indx_t)(halfbytes - lastsum) <
@ -252,7 +244,6 @@ __db_dsplit(dbp, hp, indxp, size, newfunc)
} }
*indxp = i; *indxp = i;
lastsum = sum; lastsum = sum;
did_indx = 1;
} }
if (B_TYPE(GET_BKEYDATA(h, i)->type) == B_KEYDATA) if (B_TYPE(GET_BKEYDATA(h, i)->type) == B_KEYDATA)
sum += BKEYDATA_SIZE(GET_BKEYDATA(h, i)->len); sum += BKEYDATA_SIZE(GET_BKEYDATA(h, i)->len);

View File

@ -1,7 +1,7 @@
/*- /*-
* See the file LICENSE for redistribution information. * See the file LICENSE for redistribution information.
* *
* Copyright (c) 1996, 1997 * Copyright (c) 1996, 1997, 1998
* Sleepycat Software. All rights reserved. * Sleepycat Software. All rights reserved.
*/ */
/* /*
@ -47,22 +47,19 @@
#include "config.h" #include "config.h"
#ifndef lint #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 */ #endif /* not lint */
#ifndef NO_SYSTEM_INCLUDES #ifndef NO_SYSTEM_INCLUDES
#include <sys/types.h> #include <sys/types.h>
#include <errno.h> #include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h> #include <string.h>
#endif #endif
#include "db_int.h" #include "db_int.h"
#include "db_page.h" #include "db_page.h"
#include "db_am.h" #include "db_am.h"
#include "common_ext.h"
/* /*
* Big key/data code. * Big key/data code.
@ -91,9 +88,9 @@ __db_goff(dbp, dbt, tlen, pgno, bpp, bpsz)
{ {
PAGE *h; PAGE *h;
db_indx_t bytes; db_indx_t bytes;
int ret;
u_int32_t curoff, needed, start; u_int32_t curoff, needed, start;
u_int8_t *p, *src; u_int8_t *p, *src;
int ret;
/* /*
* Check if the buffer is big enough; if it is not and we are * 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 -- * __db_ovref --
* Increment/decrement the reference count on an overflow page. * 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 int
__db_ovref(dbp, pgno, adjust) __db_ovref(dbp, pgno, adjust)
DB *dbp; DB *dbp;
db_pgno_t pgno; db_pgno_t pgno;
int adjust; int32_t adjust;
{ {
PAGE *h; PAGE *h;
int ret; int ret;
@ -277,7 +274,7 @@ __db_ovref(dbp, pgno, adjust)
if (DB_LOGGING(dbp)) if (DB_LOGGING(dbp))
if ((ret = __db_ovref_log(dbp->dbenv->lg_info, dbp->txn, 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) &LSN(h))) != 0)
return (ret); return (ret);
OV_REF(h) += adjust; OV_REF(h) += adjust;
@ -353,8 +350,8 @@ __db_moff(dbp, dbt, pgno)
{ {
PAGE *pagep; PAGE *pagep;
u_int32_t cmp_bytes, key_left; u_int32_t cmp_bytes, key_left;
int ret;
u_int8_t *p1, *p2; u_int8_t *p1, *p2;
int ret;
/* While there are both keys to compare. */ /* While there are both keys to compare. */
for (ret = 0, p1 = dbt->data, for (ret = 0, p1 = dbt->data,

View File

@ -1,14 +1,14 @@
/*- /*-
* See the file LICENSE for redistribution information. * See the file LICENSE for redistribution information.
* *
* Copyright (c) 1996, 1997 * Copyright (c) 1996, 1997, 1998
* Sleepycat Software. All rights reserved. * Sleepycat Software. All rights reserved.
*/ */
#include "config.h" #include "config.h"
#ifndef lint #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 */ #endif /* not lint */
#ifndef NO_SYSTEM_INCLUDES #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 <ctype.h>
#include <errno.h> #include <errno.h>
#include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <unistd.h> #include <unistd.h>
@ -160,7 +159,7 @@ __db_prdb(dbp)
} }
fprintf(fp, "%s ", t); fprintf(fp, "%s ", t);
__db_prflags(dbp->flags, fn); __db_prflags(dbp->flags, fn, fp);
fprintf(fp, "\n"); fprintf(fp, "\n");
return (0); return (0);
@ -179,12 +178,16 @@ __db_prbtree(dbp)
static const FN mfn[] = { static const FN mfn[] = {
{ BTM_DUP, "duplicates" }, { BTM_DUP, "duplicates" },
{ BTM_RECNO, "recno" }, { BTM_RECNO, "recno" },
{ BTM_RECNUM, "btree:records" },
{ BTM_FIXEDLEN, "recno:fixed-length" },
{ BTM_RENUMBER, "recno:renumber" },
{ 0 }, { 0 },
}; };
BTMETA *mp; BTMETA *mp;
BTREE *t; BTREE *t;
EPG *epg; EPG *epg;
FILE *fp; FILE *fp;
PAGE *h;
RECNO *rp; RECNO *rp;
db_pgno_t i; db_pgno_t i;
int ret; int ret;
@ -193,19 +196,29 @@ __db_prbtree(dbp)
fp = __db_prinit(NULL); fp = __db_prinit(NULL);
(void)fprintf(fp, "%s\nOn-page metadata:\n", DB_LINE); (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) if ((ret = __bam_pget(dbp, (PAGE **)&mp, &i, 0)) != 0)
return (ret); return (ret);
(void)fprintf(fp, "magic %#lx\n", (u_long)mp->magic); (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, "pagesize %lu\n", (u_long)mp->pagesize);
(void)fprintf(fp, "maxkey: %lu minkey: %lu\n", (void)fprintf(fp, "maxkey: %lu minkey: %lu\n",
(u_long)mp->maxkey, (u_long)mp->minkey); (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); (void)fprintf(fp, "free %lu", (u_long)mp->free);
__db_prflags(mp->flags, mfn); 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)fprintf(fp, "\n");
(void)memp_fput(dbp->mpf, mp, 0); (void)memp_fput(dbp->mpf, mp, 0);
@ -576,7 +589,7 @@ __db_isbad(h, die)
BKEYDATA *bk; BKEYDATA *bk;
FILE *fp; FILE *fp;
db_indx_t i; db_indx_t i;
int type; u_int type;
fp = __db_prinit(NULL); fp = __db_prinit(NULL);
@ -668,7 +681,8 @@ __db_pr(p, len)
u_int32_t len; u_int32_t len;
{ {
FILE *fp; FILE *fp;
int i, lastch; u_int lastch;
int i;
fp = __db_prinit(NULL); fp = __db_prinit(NULL);
@ -681,7 +695,7 @@ __db_pr(p, len)
if (isprint(*p) || *p == '\n') if (isprint(*p) || *p == '\n')
fprintf(fp, "%c", *p); fprintf(fp, "%c", *p);
else else
fprintf(fp, "%#x", (u_int)*p); fprintf(fp, "0x%.2x", (u_int)*p);
} }
if (len > 20) { if (len > 20) {
fprintf(fp, "..."); fprintf(fp, "...");
@ -692,6 +706,50 @@ __db_pr(p, len)
fprintf(fp, "\n"); fprintf(fp, "\n");
} }
/*
* __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 -- * __db_proff --
* Print out an off-page element. * Print out an off-page element.
@ -721,23 +779,21 @@ __db_proff(vp)
* __db_prflags -- * __db_prflags --
* Print out flags values. * 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 void
__db_prflags(flags, fn) __db_prflags(flags, fn, fp)
u_int32_t flags; u_int32_t flags;
FN const *fn; FN const *fn;
{
FILE *fp; FILE *fp;
{
const FN *fnp; const FN *fnp;
int found; int found;
const char *sep; const char *sep;
fp = __db_prinit(NULL);
sep = " ("; sep = " (";
for (found = 0, fnp = fn; fnp->mask != 0; ++fnp) 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); fprintf(fp, "%s%s", sep, fnp->name);
sep = ", "; sep = ", ";
found = 1; found = 1;

View File

@ -1,30 +1,25 @@
/*- /*-
* See the file LICENSE for redistribution information. * See the file LICENSE for redistribution information.
* *
* Copyright (c) 1996, 1997 * Copyright (c) 1996, 1997, 1998
* Sleepycat Software. All rights reserved. * Sleepycat Software. All rights reserved.
*/ */
#include "config.h" #include "config.h"
#ifndef lint #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 */ #endif /* not lint */
#ifndef NO_SYSTEM_INCLUDES #ifndef NO_SYSTEM_INCLUDES
#include <sys/types.h> #include <sys/types.h>
#endif
#include <ctype.h>
#include <errno.h>
#include <stddef.h>
#include <stdlib.h>
#include <string.h> #include <string.h>
#endif
#include "db_int.h" #include "db_int.h"
#include "shqueue.h" #include "shqueue.h"
#include "db_page.h" #include "db_page.h"
#include "db_dispatch.h"
#include "log.h" #include "log.h"
#include "hash.h" #include "hash.h"
#include "btree.h" #include "btree.h"
@ -48,7 +43,8 @@ __db_addrem_recover(logp, dbtp, lsnp, redo, info)
DB *file_dbp, *mdbp; DB *file_dbp, *mdbp;
DB_MPOOLFILE *mpf; DB_MPOOLFILE *mpf;
PAGE *pagep; 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_PRINT(__db_addrem_print);
REC_INTRO(__db_addrem_read); REC_INTRO(__db_addrem_read);
@ -193,7 +189,8 @@ __db_big_recover(logp, dbtp, lsnp, redo, info)
DB *file_dbp, *mdbp; DB *file_dbp, *mdbp;
DB_MPOOLFILE *mpf; DB_MPOOLFILE *mpf;
PAGE *pagep; 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_PRINT(__db_big_print);
REC_INTRO(__db_big_read); REC_INTRO(__db_big_read);
@ -503,7 +500,8 @@ __db_addpage_recover(logp, dbtp, lsnp, redo, info)
DB *file_dbp, *mdbp; DB *file_dbp, *mdbp;
DB_MPOOLFILE *mpf; DB_MPOOLFILE *mpf;
PAGE *pagep; 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_PRINT(__db_addpage_print);
REC_INTRO(__db_addpage_read); REC_INTRO(__db_addpage_read);
@ -601,8 +599,7 @@ __db_debug_recover(logp, dbtp, lsnp, redo, info)
* __db_noop_recover -- * __db_noop_recover --
* Recovery function for noop. * Recovery function for noop.
* *
* PUBLIC: int __db_noop_recover * PUBLIC: int __db_noop_recover __P((DB_LOG *, DBT *, DB_LSN *, int, void *));
* PUBLIC: __P((DB_LOG *, DBT *, DB_LSN *, int, void *));
*/ */
int int
__db_noop_recover(logp, dbtp, lsnp, redo, info) __db_noop_recover(logp, dbtp, lsnp, redo, info)
@ -613,16 +610,30 @@ __db_noop_recover(logp, dbtp, lsnp, redo, info)
void *info; void *info;
{ {
__db_noop_args *argp; __db_noop_args *argp;
int ret; DB *file_dbp, *mdbp;
DB_MPOOLFILE *mpf;
COMPQUIET(redo, 0); PAGE *pagep;
COMPQUIET(logp, NULL); u_int32_t change;
int cmp_n, cmp_p, ret;
REC_PRINT(__db_noop_print); 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; *lsnp = argp->prev_lsn;
ret = 0; ret = memp_fput(mpf, pagep, change);
REC_NOOP_CLOSE; out: REC_CLOSE;
} }

View File

@ -1,29 +1,26 @@
/*- /*-
* See the file LICENSE for redistribution information. * See the file LICENSE for redistribution information.
* *
* Copyright (c) 1996, 1997 * Copyright (c) 1996, 1997, 1998
* Sleepycat Software. All rights reserved. * Sleepycat Software. All rights reserved.
*/ */
#include "config.h" #include "config.h"
#ifndef lint #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 */ #endif /* not lint */
#ifndef NO_SYSTEM_INCLUDES #ifndef NO_SYSTEM_INCLUDES
#include <sys/types.h> #include <sys/types.h>
#include <errno.h> #include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h> #include <string.h>
#endif #endif
#include "db_int.h" #include "db_int.h"
#include "db_page.h" #include "db_page.h"
#include "btree.h" #include "btree.h"
#include "hash.h"
#include "db_am.h" #include "db_am.h"
/* /*

View File

@ -1,27 +1,25 @@
/*- /*-
* See the file LICENSE for redistribution information. * See the file LICENSE for redistribution information.
* *
* Copyright (c) 1996, 1997 * Copyright (c) 1996, 1997, 1998
* Sleepycat Software. All rights reserved. * Sleepycat Software. All rights reserved.
*/ */
#include "config.h" #include "config.h"
#ifndef lint #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 */ #endif /* not lint */
#ifndef NO_SYSTEM_INCLUDES #ifndef NO_SYSTEM_INCLUDES
#include <sys/types.h> #include <sys/types.h>
#include <errno.h> #include <errno.h>
#include <stdlib.h>
#include <string.h> #include <string.h>
#endif #endif
#include "db_int.h" #include "db_int.h"
#include "db_page.h" #include "db_page.h"
#include "shqueue.h"
#include "db_am.h" #include "db_am.h"
static int __db_getlockid __P((DB *, DB *)); static int __db_getlockid __P((DB *, DB *));

View File

@ -1,7 +1,7 @@
/*- /*-
* See the file LICENSE for redistribution information. * See the file LICENSE for redistribution information.
* *
* Copyright (c) 1996, 1997 * Copyright (c) 1996, 1997, 1998
* Sleepycat Software. All rights reserved. * Sleepycat Software. All rights reserved.
*/ */
@ -9,9 +9,9 @@
#ifndef lint #ifndef lint
static const char copyright[] = static const char copyright[] =
"@(#) Copyright (c) 1997\n\ "@(#) Copyright (c) 1996, 1997, 1998\n\
Sleepycat Software Inc. All rights reserved.\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 #endif
#ifndef NO_SYSTEM_INCLUDES #ifndef NO_SYSTEM_INCLUDES
@ -20,7 +20,6 @@ static const char sccsid[] = "@(#)db185.c 8.14 (Sleepycat) 10/25/97";
#include <errno.h> #include <errno.h>
#include <fcntl.h> #include <fcntl.h>
#include <stdlib.h> #include <stdlib.h>
#include <stdio.h>
#include <string.h> #include <string.h>
#include <unistd.h> #include <unistd.h>
#endif #endif
@ -114,6 +113,16 @@ __dbopen(file, oflags, mode, type, openinfo)
* and DB 2.0 doesn't. * 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 * Note, the file name in DB 1.85 was a const -- we don't do
* that in DB 2.0, so do that cast. * 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)); (void)__os_close(__os_open(file, oflags, mode));
dbinfop->re_source = (char *)file; dbinfop->re_source = (char *)file;
file = NULL; file = NULL;
if (O_RDONLY)
oflags &= ~O_RDONLY;
oflags |= O_RDWR;
} }
if ((ri = openinfo) != NULL) { 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 * Store the returned pointer to the real DB 2.0 structure in the
* internal pointer. Ugly, but we're not going for pretty, here. * internal pointer. Ugly, but we're not going for pretty, here.
*/ */
if ((__set_errno(db_open(file, if ((errno = db_open(file,
type, __db_oflags(oflags), mode, NULL, dbinfop, &dbp))) != 0) { type, __db_oflags(oflags), mode, NULL, dbinfop, &dbp)) != 0) {
__db_free(db185p); __db_free(db185p);
return (NULL); return (NULL);
} }
/* Create the cursor used for sequential ops. */ /* Create the cursor used for sequential ops. */
if ((__set_errno(dbp->cursor(dbp, NULL, &((DB185 *)db185p)->dbc))) if ((errno = dbp->cursor(dbp, NULL, &((DB185 *)db185p)->dbc)) != 0) {
!= 0) {
s_errno = errno; s_errno = errno;
(void)dbp->close(dbp, 0); (void)dbp->close(dbp, 0);
__db_free(db185p); __db_free(db185p);

View File

@ -1,7 +1,7 @@
/*- /*-
* See the file LICENSE for redistribution information. * See the file LICENSE for redistribution information.
* *
* Copyright (c) 1997 * Copyright (c) 1997, 1998
* Sleepycat Software. All rights reserved. * Sleepycat Software. All rights reserved.
*/ */
/* /*
@ -40,7 +40,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE. * SUCH DAMAGE.
* *
* @(#)db185_int.h 8.4 (Sleepycat) 7/27/97 * @(#)db185_int.h 8.7 (Sleepycat) 4/10/98
*/ */
#ifndef _DB185_H_ #ifndef _DB185_H_
@ -90,11 +90,11 @@ typedef struct __db185 {
/* Structure used to pass parameters to the btree routines. */ /* Structure used to pass parameters to the btree routines. */
typedef struct { typedef struct {
#define R_DUP 0x01 /* duplicate keys */ #define R_DUP 0x01 /* duplicate keys */
u_long flags; u_int32_t flags;
u_int cachesize; /* bytes to cache */ u_int32_t cachesize; /* bytes to cache */
int maxkeypage; /* maximum keys per page */ u_int32_t maxkeypage; /* maximum keys per page */
int minkeypage; /* minimum keys per page */ u_int32_t minkeypage; /* minimum keys per page */
u_int psize; /* page size */ u_int32_t psize; /* page size */
int (*compare) /* comparison function */ int (*compare) /* comparison function */
__P((const DBT *, const DBT *)); __P((const DBT *, const DBT *));
size_t (*prefix) /* prefix function */ size_t (*prefix) /* prefix function */
@ -104,10 +104,10 @@ typedef struct {
/* Structure used to pass parameters to the hashing routines. */ /* Structure used to pass parameters to the hashing routines. */
typedef struct { typedef struct {
u_int bsize; /* bucket size */ u_int32_t bsize; /* bucket size */
u_int ffactor; /* fill factor */ u_int32_t ffactor; /* fill factor */
u_int nelem; /* number of elements */ u_int32_t nelem; /* number of elements */
u_int cachesize; /* bytes to cache */ u_int32_t cachesize; /* bytes to cache */
u_int32_t /* hash function */ u_int32_t /* hash function */
(*hash) __P((const void *, size_t)); (*hash) __P((const void *, size_t));
int lorder; /* byte order */ int lorder; /* byte order */
@ -118,9 +118,9 @@ typedef struct {
#define R_FIXEDLEN 0x01 /* fixed-length records */ #define R_FIXEDLEN 0x01 /* fixed-length records */
#define R_NOKEY 0x02 /* key not required */ #define R_NOKEY 0x02 /* key not required */
#define R_SNAPSHOT 0x04 /* snapshot the input */ #define R_SNAPSHOT 0x04 /* snapshot the input */
u_long flags; u_int32_t flags;
u_int cachesize; /* bytes to cache */ u_int32_t cachesize; /* bytes to cache */
u_int psize; /* page size */ u_int32_t psize; /* page size */
int lorder; /* byte order */ int lorder; /* byte order */
size_t reclen; /* record length (fixed-length records) */ size_t reclen; /* record length (fixed-length records) */
u_char bval; /* delimiting byte (variable-length records */ u_char bval; /* delimiting byte (variable-length records */

View File

@ -1,7 +1,7 @@
/*- /*-
* See the file LICENSE for redistribution information. * See the file LICENSE for redistribution information.
* *
* Copyright (c) 1996, 1997 * Copyright (c) 1996, 1997, 1998
* Sleepycat Software. All rights reserved. * Sleepycat Software. All rights reserved.
*/ */
/* /*
@ -36,7 +36,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE. * 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_ #ifndef _DB_185_H_
@ -127,11 +127,11 @@ typedef struct __db {
/* Structure used to pass parameters to the btree routines. */ /* Structure used to pass parameters to the btree routines. */
typedef struct { typedef struct {
#define R_DUP 0x01 /* duplicate keys */ #define R_DUP 0x01 /* duplicate keys */
u_long flags; u_int32_t flags;
u_int cachesize; /* bytes to cache */ u_int32_t cachesize; /* bytes to cache */
int maxkeypage; /* maximum keys per page */ u_int32_t maxkeypage; /* maximum keys per page */
int minkeypage; /* minimum keys per page */ u_int32_t minkeypage; /* minimum keys per page */
u_int psize; /* page size */ u_int32_t psize; /* page size */
int (*compare) /* comparison function */ int (*compare) /* comparison function */
__P((const DBT *, const DBT *)); __P((const DBT *, const DBT *));
size_t (*prefix) /* prefix function */ size_t (*prefix) /* prefix function */
@ -144,10 +144,10 @@ typedef struct {
/* Structure used to pass parameters to the hashing routines. */ /* Structure used to pass parameters to the hashing routines. */
typedef struct { typedef struct {
u_int bsize; /* bucket size */ u_int32_t bsize; /* bucket size */
u_int ffactor; /* fill factor */ u_int32_t ffactor; /* fill factor */
u_int nelem; /* number of elements */ u_int32_t nelem; /* number of elements */
u_int cachesize; /* bytes to cache */ u_int32_t cachesize; /* bytes to cache */
u_int32_t /* hash function */ u_int32_t /* hash function */
(*hash) __P((const void *, size_t)); (*hash) __P((const void *, size_t));
int lorder; /* byte order */ int lorder; /* byte order */
@ -158,9 +158,9 @@ typedef struct {
#define R_FIXEDLEN 0x01 /* fixed-length records */ #define R_FIXEDLEN 0x01 /* fixed-length records */
#define R_NOKEY 0x02 /* key not required */ #define R_NOKEY 0x02 /* key not required */
#define R_SNAPSHOT 0x04 /* snapshot the input */ #define R_SNAPSHOT 0x04 /* snapshot the input */
u_long flags; u_int32_t flags;
u_int cachesize; /* bytes to cache */ u_int32_t cachesize; /* bytes to cache */
u_int psize; /* page size */ u_int32_t psize; /* page size */
int lorder; /* byte order */ int lorder; /* byte order */
size_t reclen; /* record length (fixed-length records) */ size_t reclen; /* record length (fixed-length records) */
u_char bval; /* delimiting byte (variable-length records */ u_char bval; /* delimiting byte (variable-length records */

View File

@ -1,10 +1,10 @@
/*- /*-
* See the file LICENSE for redistribution information. * See the file LICENSE for redistribution information.
* *
* Copyright (c) 1996, 1997 * Copyright (c) 1996, 1997, 1998
* Sleepycat Software. All rights reserved. * 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_ #ifndef _DB_INTERNAL_H_
@ -12,8 +12,6 @@
#include "db.h" /* Standard DB include file. */ #include "db.h" /* Standard DB include file. */
#include "queue.h" #include "queue.h"
#include "os_func.h"
#include "os_ext.h"
/******************************************************* /*******************************************************
* General purpose constants and macros. * General purpose constants and macros.
@ -77,8 +75,8 @@
#define R_ADDR(base, offset) ((void *)((u_int8_t *)((base)->addr) + offset)) #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) #define R_OFFSET(base, p) ((u_int8_t *)(p) - (u_int8_t *)(base)->addr)
/* Free and free-string macros that overwrite memory during debugging. */ /* Free and free-string macros that overwrite memory. */
#ifdef DEBUG #ifdef DIAGNOSTIC
#undef FREE #undef FREE
#define FREE(p, len) { \ #define FREE(p, len) { \
memset(p, 0xff, len); \ memset(p, 0xff, len); \
@ -117,36 +115,41 @@ typedef struct __fn {
#undef DB_LINE #undef DB_LINE
#define 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!" */ /* Unused, or not-used-yet variable. "Shut that bloody compiler up!" */
#define COMPQUIET(n, v) (n) = (v) #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. * Files.
*******************************************************/ *******************************************************/
#ifndef MAXPATHLEN /* Maximum path length. */ /*
#ifdef PATH_MAX * We use 1024 as the maximum path length. It's too hard to figure out what
#define MAXPATHLEN PATH_MAX * the real path length is, as it was traditionally stored in <sys/param.h>,
#else * and that file isn't always available.
*/
#undef MAXPATHLEN
#define MAXPATHLEN 1024 #define MAXPATHLEN 1024
#endif
#endif
#define PATH_DOT "." /* Current working directory. */ #define PATH_DOT "." /* Current working directory. */
#define PATH_SEPARATOR "/" /* Path separator character. */ #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. * Mutex support.
*******************************************************/ *******************************************************/
@ -176,12 +179,12 @@ typedef unsigned char tsl_t;
typedef struct _db_mutex_t { typedef struct _db_mutex_t {
#ifdef HAVE_SPINLOCKS #ifdef HAVE_SPINLOCKS
tsl_t tsl_resource; /* Resource test and set. */ tsl_t tsl_resource; /* Resource test and set. */
#ifdef DEBUG #ifdef DIAGNOSTIC
u_long pid; /* Lock holder: 0 or process pid. */ u_int32_t pid; /* Lock holder: 0 or process pid. */
#endif #endif
#else #else
u_int32_t off; /* Backing file offset. */ 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 #endif
u_int32_t spins; /* Spins before block. */ u_int32_t spins; /* Spins before block. */
u_int32_t mutex_set_wait; /* Granted after wait. */ u_int32_t mutex_set_wait; /* Granted after wait. */
@ -195,11 +198,11 @@ typedef struct _db_mutex_t {
*******************************************************/ *******************************************************/
/* Lock/unlock a DB thread. */ /* Lock/unlock a DB thread. */
#define DB_THREAD_LOCK(dbp) \ #define DB_THREAD_LOCK(dbp) \
(F_ISSET(dbp, DB_AM_THREAD) ? \ if (F_ISSET(dbp, DB_AM_THREAD)) \
__db_mutex_lock((db_mutex_t *)(dbp)->mutexp, -1) : 0) (void)__db_mutex_lock((db_mutex_t *)(dbp)->mutexp, -1);
#define DB_THREAD_UNLOCK(dbp) \ #define DB_THREAD_UNLOCK(dbp) \
(F_ISSET(dbp, DB_AM_THREAD) ? \ if (F_ISSET(dbp, DB_AM_THREAD)) \
__db_mutex_unlock((db_mutex_t *)(dbp)->mutexp, -1) : 0) (void)__db_mutex_unlock((db_mutex_t *)(dbp)->mutexp, -1);
/* Btree/recno local statistics structure. */ /* Btree/recno local statistics structure. */
struct __db_bt_lstat; typedef struct __db_bt_lstat DB_BTREE_LSTAT; struct __db_bt_lstat; typedef struct __db_bt_lstat DB_BTREE_LSTAT;
@ -228,7 +231,7 @@ typedef enum {
} APPNAME; } APPNAME;
/******************************************************* /*******************************************************
* Regions. * Shared memory regions.
*******************************************************/ *******************************************************/
/* /*
* The shared memory regions share an initial structure so that the general * The shared memory regions share an initial structure so that the general
@ -240,16 +243,69 @@ typedef enum {
*/ */
typedef struct _rlayout { typedef struct _rlayout {
db_mutex_t lock; /* Region mutex. */ db_mutex_t lock; /* Region mutex. */
#define DB_REGIONMAGIC 0x120897
u_int32_t valid; /* Valid magic number. */
u_int32_t refcnt; /* Region reference count. */ u_int32_t refcnt; /* Region reference count. */
size_t size; /* Region length. */ size_t size; /* Region length. */
int majver; /* Major version number. */ int majver; /* Major version number. */
int minver; /* Minor version number. */ int minver; /* Minor version number. */
int patch; /* Patch 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; u_int32_t flags;
} RLAYOUT; } 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. * Mpool.
*******************************************************/ *******************************************************/
@ -281,7 +337,7 @@ typedef struct __dbpginfo {
#define DB_LOGGING(dbp) \ #define DB_LOGGING(dbp) \
(F_ISSET(dbp, DB_AM_LOGGING) && !F_ISSET(dbp, DB_AM_RECOVER)) (F_ISSET(dbp, DB_AM_LOGGING) && !F_ISSET(dbp, DB_AM_RECOVER))
#ifdef DEBUG #ifdef DIAGNOSTIC
/* /*
* Debugging macro to log operations. * Debugging macro to log operations.
* If DEBUG_WOP is defined, log operations that modify the database. * If DEBUG_WOP is defined, log operations that modify the database.
@ -318,7 +374,7 @@ typedef struct __dbpginfo {
#else #else
#define DEBUG_LREAD(D, T, O, K, A, F) #define DEBUG_LREAD(D, T, O, K, A, F)
#define DEBUG_LWRITE(D, T, O, K, A, F) #define DEBUG_LWRITE(D, T, O, K, A, F)
#endif /* DEBUG */ #endif /* DIAGNOSTIC */
/******************************************************* /*******************************************************
* Transactions and recovery. * Transactions and recovery.
@ -339,4 +395,8 @@ struct __db_txn {
size_t off; /* Detail structure within region. */ size_t off; /* Detail structure within region. */
TAILQ_ENTRY(__db_txn) links; TAILQ_ENTRY(__db_txn) links;
}; };
#include "os_func.h"
#include "os_ext.h"
#endif /* !_DB_INTERNAL_H_ */ #endif /* !_DB_INTERNAL_H_ */

View File

@ -1,7 +1,7 @@
/*- /*-
* See the file LICENSE for redistribution information. * See the file LICENSE for redistribution information.
* *
* Copyright (c) 1996, 1997 * Copyright (c) 1996, 1997, 1998
* Sleepycat Software. All rights reserved. * Sleepycat Software. All rights reserved.
*/ */
/* /*
@ -47,15 +47,14 @@
#include "config.h" #include "config.h"
#ifndef lint #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 */ #endif /* not lint */
#ifndef NO_SYSTEM_INCLUDES #ifndef NO_SYSTEM_INCLUDES
#include <sys/param.h> #include <sys/types.h>
#include <errno.h> #include <errno.h>
#include <fcntl.h> #include <fcntl.h>
#include <stdio.h>
#include <string.h> #include <string.h>
#endif #endif
@ -82,7 +81,7 @@ __db_dbm_init(file)
if (__cur_db != NULL) if (__cur_db != NULL)
(void)dbm_close(__cur_db); (void)dbm_close(__cur_db);
if ((__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); return (0);
if ((__cur_db = dbm_open(file, O_RDONLY, 0)) != NULL) if ((__cur_db = dbm_open(file, O_RDONLY, 0)) != NULL)
return (0); return (0);
@ -244,19 +243,19 @@ __db_ndbm_fetch(db, key)
{ {
DBT _key, _data; DBT _key, _data;
datum data; datum data;
int status; int ret;
memset(&_key, 0, sizeof(DBT)); memset(&_key, 0, sizeof(DBT));
memset(&_data, 0, sizeof(DBT)); memset(&_data, 0, sizeof(DBT));
_key.size = key.dsize; _key.size = key.dsize;
_key.data = key.dptr; _key.data = key.dptr;
status = db->get((DB *)db, NULL, &_key, &_data, 0); if ((ret = db->get((DB *)db, NULL, &_key, &_data, 0)) == 0) {
if (status) {
data.dptr = NULL;
data.dsize = 0;
} else {
data.dptr = _data.data; data.dptr = _data.data;
data.dsize = _data.size; data.dsize = _data.size;
} else {
data.dptr = NULL;
data.dsize = 0;
__set_errno (ret == DB_NOTFOUND ? ENOENT : ret);
} }
return (data); return (data);
} }
@ -273,7 +272,7 @@ __db_ndbm_firstkey(db)
{ {
DBT _key, _data; DBT _key, _data;
datum key; datum key;
int status; int ret;
DBC *cp; DBC *cp;
@ -285,13 +284,13 @@ __db_ndbm_firstkey(db)
memset(&_key, 0, sizeof(DBT)); memset(&_key, 0, sizeof(DBT));
memset(&_data, 0, sizeof(DBT)); memset(&_data, 0, sizeof(DBT));
status = (cp->c_get)(cp, &_key, &_data, DB_FIRST); if ((ret = (cp->c_get)(cp, &_key, &_data, DB_FIRST)) == 0) {
if (status) {
key.dptr = NULL;
key.dsize = 0;
} else {
key.dptr = _key.data; key.dptr = _key.data;
key.dsize = _key.size; key.dsize = _key.size;
} else {
key.dptr = NULL;
key.dsize = 0;
__set_errno (ret == DB_NOTFOUND ? ENOENT : ret);
} }
return (key); return (key);
} }
@ -309,7 +308,7 @@ __db_ndbm_nextkey(db)
DBC *cp; DBC *cp;
DBT _key, _data; DBT _key, _data;
datum key; datum key;
int status; int ret;
if ((cp = TAILQ_FIRST(&db->curs_queue)) == NULL) if ((cp = TAILQ_FIRST(&db->curs_queue)) == NULL)
if ((errno = db->cursor(db, NULL, &cp)) != 0) { if ((errno = db->cursor(db, NULL, &cp)) != 0) {
@ -319,13 +318,13 @@ __db_ndbm_nextkey(db)
memset(&_key, 0, sizeof(DBT)); memset(&_key, 0, sizeof(DBT));
memset(&_data, 0, sizeof(DBT)); memset(&_data, 0, sizeof(DBT));
status = (cp->c_get)(cp, &_key, &_data, DB_NEXT); if ((ret = (cp->c_get)(cp, &_key, &_data, DB_NEXT)) == 0) {
if (status) {
key.dptr = NULL;
key.dsize = 0;
} else {
key.dptr = _key.data; key.dptr = _key.data;
key.dsize = _key.size; key.dsize = _key.size;
} else {
key.dptr = NULL;
key.dsize = 0;
__set_errno (ret == DB_NOTFOUND ? ENOENT : ret);
} }
return (key); return (key);
} }
@ -347,14 +346,10 @@ __db_ndbm_delete(db, key)
memset(&_key, 0, sizeof(DBT)); memset(&_key, 0, sizeof(DBT));
_key.data = key.dptr; _key.data = key.dptr;
_key.size = key.dsize; _key.size = key.dsize;
ret = (((DB *)db)->del)((DB *)db, NULL, &_key, 0); if ((ret = (((DB *)db)->del)((DB *)db, NULL, &_key, 0)) == 0)
if (ret < 0) return (0);
errno = ENOENT; errno = ret == DB_NOTFOUND ? ENOENT : ret;
else if (ret > 0) { return (-1);
errno = ret;
ret = -1;
}
return (ret);
} }
weak_alias (__db_ndbm_delete, dbm_delete) weak_alias (__db_ndbm_delete, dbm_delete)
@ -371,6 +366,7 @@ __db_ndbm_store(db, key, data, flags)
int flags; int flags;
{ {
DBT _key, _data; DBT _key, _data;
int ret;
memset(&_key, 0, sizeof(DBT)); memset(&_key, 0, sizeof(DBT));
memset(&_data, 0, sizeof(DBT)); memset(&_data, 0, sizeof(DBT));
@ -378,8 +374,13 @@ __db_ndbm_store(db, key, data, flags)
_key.size = key.dsize; _key.size = key.dsize;
_data.data = data.dptr; _data.data = data.dptr;
_data.size = data.dsize; _data.size = data.dsize;
return (db->put((DB *)db, if ((ret = db->put((DB *)db, NULL,
NULL, &_key, &_data, (flags == DBM_INSERT) ? DB_NOOVERWRITE : 0)); &_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) weak_alias (__db_ndbm_store, dbm_store)

View File

@ -1,7 +1,7 @@
/*- /*-
* See the file LICENSE for redistribution information. * See the file LICENSE for redistribution information.
* *
* Copyright (c) 1996, 1997 * Copyright (c) 1996, 1997, 1998
* Sleepycat Software. All rights reserved. * Sleepycat Software. All rights reserved.
*/ */
/* /*
@ -47,23 +47,19 @@
#include "config.h" #include "config.h"
#ifndef lint #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 */ #endif /* not lint */
#ifndef NO_SYSTEM_INCLUDES #ifndef NO_SYSTEM_INCLUDES
#include <sys/types.h> #include <sys/types.h>
#include <sys/stat.h>
#include <errno.h> #include <errno.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <unistd.h>
#endif #endif
#include "shqueue.h"
#include "db_int.h" #include "db_int.h"
#include "shqueue.h"
#include "db_page.h" #include "db_page.h"
#include "db_am.h" #include "db_am.h"
#include "db_ext.h" #include "db_ext.h"
@ -71,20 +67,20 @@ static const char sccsid[] = "@(#)hash.c 10.36 (Sleepycat) 1/8/98";
#include "log.h" #include "log.h"
static int __ham_c_close __P((DBC *)); static int __ham_c_close __P((DBC *));
static int __ham_c_del __P((DBC *, int)); static int __ham_c_del __P((DBC *, u_int32_t));
static int __ham_c_get __P((DBC *, DBT *, DBT *, int)); static int __ham_c_get __P((DBC *, DBT *, DBT *, u_int32_t));
static int __ham_c_put __P((DBC *, DBT *, DBT *, int)); 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_c_init __P((DB *, DB_TXN *, DBC **));
static int __ham_cursor __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_delete __P((DB *, DB_TXN *, DBT *, u_int32_t));
static int __ham_dup_return __P((HTAB *, HASH_CURSOR *, DBT *, int)); static int __ham_dup_return __P((HTAB *, HASH_CURSOR *, DBT *, u_int32_t));
static int __ham_get __P((DB *, DB_TXN *, DBT *, DBT *, int)); static int __ham_get __P((DB *, DB_TXN *, DBT *, DBT *, u_int32_t));
static void __ham_init_htab __P((HTAB *, u_int)); static void __ham_init_htab __P((HTAB *, u_int32_t, u_int32_t));
static int __ham_lookup __P((HTAB *, static int __ham_lookup __P((HTAB *,
HASH_CURSOR *, const DBT *, u_int32_t, db_lockmode_t)); HASH_CURSOR *, const DBT *, u_int32_t, db_lockmode_t));
static int __ham_overwrite __P((HTAB *, HASH_CURSOR *, DBT *)); static int __ham_overwrite __P((HTAB *, HASH_CURSOR *, DBT *));
static int __ham_put __P((DB *, DB_TXN *, DBT *, DBT *, int)); static int __ham_put __P((DB *, DB_TXN *, DBT *, DBT *, u_int32_t));
static int __ham_sync __P((DB *, int)); static int __ham_sync __P((DB *, u_int32_t));
/************************** INTERFACE ROUTINES ***************************/ /************************** INTERFACE ROUTINES ***************************/
/* OPEN/CLOSE */ /* OPEN/CLOSE */
@ -175,9 +171,9 @@ __ham_open(dbp, dbinfo)
goto out; goto out;
} }
hashp->hdr->ffactor = __ham_init_htab(hashp,
dbinfo != NULL && dbinfo->h_ffactor ? dbinfo->h_ffactor : 0; 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)) if (F_ISSET(dbp, DB_AM_DUP))
F_SET(hashp->hdr, DB_HASH_DUP); F_SET(hashp->hdr, DB_HASH_DUP);
if ((ret = __ham_dirty_page(hashp, (PAGE *)hashp->hdr)) != 0) 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 int
__ham_close(dbp) __ham_close(dbp)
@ -264,13 +260,14 @@ __ham_close(dbp)
* Returns 0 on No Error * Returns 0 on No Error
*/ */
static void static void
__ham_init_htab(hashp, nelem) __ham_init_htab(hashp, nelem, ffactor)
HTAB *hashp; HTAB *hashp;
u_int nelem; u_int32_t nelem, ffactor;
{ {
int32_t l2, nbuckets; int32_t l2, nbuckets;
hashp->hdr->nelem = 0; memset(hashp->hdr, 0, sizeof(HASHHDR));
hashp->hdr->ffactor = ffactor;
hashp->hdr->pagesize = hashp->dbp->pgsize; hashp->hdr->pagesize = hashp->dbp->pgsize;
ZERO_LSN(hashp->hdr->lsn); ZERO_LSN(hashp->hdr->lsn);
hashp->hdr->magic = DB_HASHMAGIC; hashp->hdr->magic = DB_HASHMAGIC;
@ -287,8 +284,6 @@ __ham_init_htab(hashp, nelem)
nbuckets = 1 << l2; nbuckets = 1 << l2;
hashp->hdr->spares[l2] = 0;
hashp->hdr->spares[l2 + 1] = 0;
hashp->hdr->ovfl_point = l2; hashp->hdr->ovfl_point = l2;
hashp->hdr->last_freed = PGNO_INVALID; hashp->hdr->last_freed = PGNO_INVALID;
@ -310,7 +305,7 @@ __ham_init_htab(hashp, nelem)
static int static int
__ham_sync(dbp, flags) __ham_sync(dbp, flags)
DB *dbp; DB *dbp;
int flags; u_int32_t flags;
{ {
int ret; int ret;
@ -342,10 +337,9 @@ __ham_get(dbp, txn, key, data, flags)
DB_TXN *txn; DB_TXN *txn;
DBT *key; DBT *key;
DBT *data; DBT *data;
int flags; u_int32_t flags;
{ {
DB *ldbp; DB *ldbp;
DBC *cp;
HTAB *hashp; HTAB *hashp;
HASH_CURSOR *hcp; HASH_CURSOR *hcp;
int ret, t_ret; int ret, t_ret;
@ -362,7 +356,6 @@ __ham_get(dbp, txn, key, data, flags)
hashp = (HTAB *)ldbp->internal; hashp = (HTAB *)ldbp->internal;
SET_LOCKER(ldbp, txn); SET_LOCKER(ldbp, txn);
GET_META(ldbp, hashp); GET_META(ldbp, hashp);
cp = TAILQ_FIRST(&ldbp->curs_queue);
hashp->hash_accesses++; hashp->hash_accesses++;
hcp = (HASH_CURSOR *)TAILQ_FIRST(&ldbp->curs_queue)->internal; hcp = (HASH_CURSOR *)TAILQ_FIRST(&ldbp->curs_queue)->internal;
@ -386,14 +379,14 @@ __ham_put(dbp, txn, key, data, flags)
DB_TXN *txn; DB_TXN *txn;
DBT *key; DBT *key;
DBT *data; DBT *data;
int flags; u_int32_t flags;
{ {
DB *ldbp; DB *ldbp;
HTAB *hashp;
HASH_CURSOR *hcp;
DBT tmp_val, *myval; DBT tmp_val, *myval;
int ret, t_ret; HASH_CURSOR *hcp;
HTAB *hashp;
u_int32_t nbytes; u_int32_t nbytes;
int ret, t_ret;
DEBUG_LWRITE(dbp, txn, "ham_put", key, data, flags); DEBUG_LWRITE(dbp, txn, "ham_put", key, data, flags);
if ((ret = __db_putchk(dbp, key, data, if ((ret = __db_putchk(dbp, key, data,
@ -531,7 +524,7 @@ __ham_delete(dbp, txn, key, flags)
DB *dbp; DB *dbp;
DB_TXN *txn; DB_TXN *txn;
DBT *key; DBT *key;
int flags; u_int32_t flags;
{ {
DB *ldbp; DB *ldbp;
HTAB *hashp; HTAB *hashp;
@ -539,7 +532,8 @@ __ham_delete(dbp, txn, key, flags)
int ret, t_ret; int ret, t_ret;
DEBUG_LWRITE(dbp, txn, "ham_delete", key, NULL, flags); 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); return (ret);
ldbp = dbp; ldbp = dbp;
@ -639,12 +633,12 @@ __ham_c_iclose(dbp, dbc)
static int static int
__ham_c_del(cursor, flags) __ham_c_del(cursor, flags)
DBC *cursor; DBC *cursor;
int flags; u_int32_t flags;
{ {
DB *ldbp; DB *ldbp;
HTAB *hashp;
HASH_CURSOR *hcp; HASH_CURSOR *hcp;
HASH_CURSOR save_curs; HASH_CURSOR save_curs;
HTAB *hashp;
db_pgno_t ppgno, chg_pgno; db_pgno_t ppgno, chg_pgno;
int ret, t_ret; int ret, t_ret;
@ -756,7 +750,7 @@ __ham_c_del(cursor, flags)
normal: ret = __ham_del_pair(hashp, hcp, 1); normal: ret = __ham_del_pair(hashp, hcp, 1);
out: if ((t_ret = __ham_item_done(hashp, hcp, ret == 0)) != 0 && ret == 0) out: if ((t_ret = __ham_item_done(hashp, hcp, ret == 0)) != 0 && ret == 0)
t_ret = ret; ret = t_ret;
if (ret != 0) if (ret != 0)
*hcp = save_curs; *hcp = save_curs;
RELEASE_META(hashp->dbp, hashp); RELEASE_META(hashp->dbp, hashp);
@ -770,7 +764,7 @@ __ham_c_get(cursor, key, data, flags)
DBC *cursor; DBC *cursor;
DBT *key; DBT *key;
DBT *data; DBT *data;
int flags; u_int32_t flags;
{ {
DB *ldbp; DB *ldbp;
HTAB *hashp; HTAB *hashp;
@ -805,7 +799,7 @@ __ham_c_get(cursor, key, data, flags)
ret = __ham_item_prev(hashp, hcp, DB_LOCK_READ); ret = __ham_item_prev(hashp, hcp, DB_LOCK_READ);
break; break;
} }
/* FALL THROUGH */ /* FALLTHROUGH */
case DB_LAST: case DB_LAST:
ret = __ham_item_last(hashp, hcp, DB_LOCK_READ); ret = __ham_item_last(hashp, hcp, DB_LOCK_READ);
break; 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) out1: if ((t_ret = __ham_item_done(hashp, hcp, 0)) != 0 && ret == 0)
t_ret = ret; ret = t_ret;
out: if (ret) out: if (ret)
*hcp = save_curs; *hcp = save_curs;
RELEASE_META(hashp->dbp, hashp); RELEASE_META(hashp->dbp, hashp);
@ -907,17 +901,17 @@ __ham_c_put(cursor, key, data, flags)
DBC *cursor; DBC *cursor;
DBT *key; DBT *key;
DBT *data; DBT *data;
int flags; u_int32_t flags;
{ {
DB *ldbp; DB *ldbp;
HTAB *hashp;
HASH_CURSOR *hcp, save_curs; HASH_CURSOR *hcp, save_curs;
int ret, t_ret; HTAB *hashp;
u_int32_t nbytes; u_int32_t nbytes;
int ret, t_ret;
DEBUG_LWRITE(cursor->dbp, cursor->txn, "ham_c_put", DEBUG_LWRITE(cursor->dbp, cursor->txn, "ham_c_put",
flags == DB_KEYFIRST || flags == DB_KEYLAST ? key : NULL, flags == DB_KEYFIRST || flags == DB_KEYLAST ? key : NULL,
NULL, flags); data, flags);
ldbp = cursor->dbp; ldbp = cursor->dbp;
if (F_ISSET(cursor->dbp, DB_AM_THREAD) && if (F_ISSET(cursor->dbp, DB_AM_THREAD) &&
(ret = __db_gethandle(cursor->dbp, __ham_hdup, &ldbp)) != 0) (ret = __db_gethandle(cursor->dbp, __ham_hdup, &ldbp)) != 0)
@ -1087,14 +1081,14 @@ __ham_dup_return(hashp, hcp, val, flags)
HTAB *hashp; HTAB *hashp;
HASH_CURSOR *hcp; HASH_CURSOR *hcp;
DBT *val; DBT *val;
int flags; u_int32_t flags;
{ {
PAGE *pp; PAGE *pp;
DBT *myval, tmp_val; DBT *myval, tmp_val;
db_indx_t ndx; db_indx_t ndx;
db_pgno_t pgno; db_pgno_t pgno;
u_int8_t *hk, type; u_int8_t *hk, type;
int indx, ret; int ret;
db_indx_t len; db_indx_t len;
/* Check for duplicate and return the first one. */ /* 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)), memcpy(&pgno, HOFFDUP_PGNO(P_ENTRY(hcp->pagep, ndx)),
sizeof(db_pgno_t)); sizeof(db_pgno_t));
if (flags == DB_LAST || flags == DB_PREV) { if (flags == DB_LAST || flags == DB_PREV) {
indx = (int)hcp->dndx;
if ((ret = __db_dend(hashp->dbp, if ((ret = __db_dend(hashp->dbp,
pgno, &hcp->dpagep)) != 0) pgno, &hcp->dpagep)) != 0)
return (ret); return (ret);
@ -1451,14 +1444,15 @@ __ham_c_update(hcp, chg_pgno, len, add, is_dup)
* __ham_hdup -- * __ham_hdup --
* This function gets called when we create a duplicate handle for a * This function gets called when we create a duplicate handle for a
* threaded DB. It should create the private part of the DB structure. * threaded DB. It should create the private part of the DB structure.
*
* PUBLIC: int __ham_hdup __P((DB *, DB *)); * PUBLIC: int __ham_hdup __P((DB *, DB *));
*/ */
int int
__ham_hdup(orig, new) __ham_hdup(orig, new)
DB *orig, *new; DB *orig, *new;
{ {
HTAB *hashp;
DBC *curs; DBC *curs;
HTAB *hashp;
int ret; int ret;
if ((hashp = (HTAB *)__db_malloc(sizeof(HTAB))) == NULL) if ((hashp = (HTAB *)__db_malloc(sizeof(HTAB))) == NULL)

View File

@ -1,7 +1,7 @@
/*- /*-
* See the file LICENSE for redistribution information. * See the file LICENSE for redistribution information.
* *
* Copyright (c) 1996, 1997 * Copyright (c) 1996, 1997, 1998
* Sleepycat Software. All rights reserved. * Sleepycat Software. All rights reserved.
*/ */
/* /*
@ -43,11 +43,9 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE. * 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 * 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 * hash package. Each access method (or set of routines wishing to register

View File

@ -15,8 +15,6 @@
#include "db_dispatch.h" #include "db_dispatch.h"
#include "hash.h" #include "hash.h"
#include "db_am.h" #include "db_am.h"
#include "common_ext.h"
/* /*
* PUBLIC: int __ham_insdel_log * PUBLIC: int __ham_insdel_log
* PUBLIC: __P((DB_LOG *, DB_TXN *, DB_LSN *, u_int32_t, * 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); memcpy(bp, data->data, data->size);
bp += data->size; bp += data->size;
} }
#ifdef DEBUG #ifdef DIAGNOSTIC
if ((u_int32_t)(bp - (u_int8_t *)logrec.data) != logrec.size) if ((u_int32_t)(bp - (u_int8_t *)logrec.data) != logrec.size)
fprintf(stderr, "Error in log record length"); fprintf(stderr, "Error in log record length");
#endif #endif
@ -120,22 +118,23 @@ int __ham_insdel_log(logp, txnid, ret_lsnp, flags,
* PUBLIC: __P((DB_LOG *, DBT *, DB_LSN *, int, void *)); * PUBLIC: __P((DB_LOG *, DBT *, DB_LSN *, int, void *));
*/ */
int int
__ham_insdel_print(notused1, dbtp, lsnp, notused3, notused4) __ham_insdel_print(notused1, dbtp, lsnp, notused2, notused3)
DB_LOG *notused1; DB_LOG *notused1;
DBT *dbtp; DBT *dbtp;
DB_LSN *lsnp; DB_LSN *lsnp;
int notused3; int notused2;
void *notused4; void *notused3;
{ {
__ham_insdel_args *argp; __ham_insdel_args *argp;
u_int32_t i; u_int32_t i;
int c, ret; u_int ch;
int ret;
i = 0; i = 0;
c = 0; ch = 0;
notused1 = NULL; notused1 = NULL;
notused3 = 0; notused2 = 0;
notused4 = NULL; notused3 = NULL;
if ((ret = __ham_insdel_read(dbtp->data, &argp)) != 0) if ((ret = __ham_insdel_read(dbtp->data, &argp)) != 0)
return (ret); return (ret);
@ -154,20 +153,20 @@ __ham_insdel_print(notused1, dbtp, lsnp, notused3, notused4)
(u_long)argp->pagelsn.file, (u_long)argp->pagelsn.offset); (u_long)argp->pagelsn.file, (u_long)argp->pagelsn.offset);
printf("\tkey: "); printf("\tkey: ");
for (i = 0; i < argp->key.size; i++) { for (i = 0; i < argp->key.size; i++) {
c = ((char *)argp->key.data)[i]; ch = ((u_int8_t *)argp->key.data)[i];
if (isprint(c) || c == 0xa) if (isprint(ch) || ch == 0xa)
putchar(c); putchar(ch);
else else
printf("%#x ", c); printf("%#x ", ch);
} }
printf("\n"); printf("\n");
printf("\tdata: "); printf("\tdata: ");
for (i = 0; i < argp->data.size; i++) { for (i = 0; i < argp->data.size; i++) {
c = ((char *)argp->data.data)[i]; ch = ((u_int8_t *)argp->data.data)[i];
if (isprint(c) || c == 0xa) if (isprint(ch) || ch == 0xa)
putchar(c); putchar(ch);
else else
printf("%#x ", c); printf("%#x ", ch);
} }
printf("\n"); printf("\n");
printf("\n"); printf("\n");
@ -300,7 +299,7 @@ int __ham_newpage_log(logp, txnid, ret_lsnp, flags,
else else
memset(bp, 0, sizeof(*nextlsn)); memset(bp, 0, sizeof(*nextlsn));
bp += sizeof(*nextlsn); bp += sizeof(*nextlsn);
#ifdef DEBUG #ifdef DIAGNOSTIC
if ((u_int32_t)(bp - (u_int8_t *)logrec.data) != logrec.size) if ((u_int32_t)(bp - (u_int8_t *)logrec.data) != logrec.size)
fprintf(stderr, "Error in log record length"); fprintf(stderr, "Error in log record length");
#endif #endif
@ -316,22 +315,23 @@ int __ham_newpage_log(logp, txnid, ret_lsnp, flags,
* PUBLIC: __P((DB_LOG *, DBT *, DB_LSN *, int, void *)); * PUBLIC: __P((DB_LOG *, DBT *, DB_LSN *, int, void *));
*/ */
int int
__ham_newpage_print(notused1, dbtp, lsnp, notused3, notused4) __ham_newpage_print(notused1, dbtp, lsnp, notused2, notused3)
DB_LOG *notused1; DB_LOG *notused1;
DBT *dbtp; DBT *dbtp;
DB_LSN *lsnp; DB_LSN *lsnp;
int notused3; int notused2;
void *notused4; void *notused3;
{ {
__ham_newpage_args *argp; __ham_newpage_args *argp;
u_int32_t i; u_int32_t i;
int c, ret; u_int ch;
int ret;
i = 0; i = 0;
c = 0; ch = 0;
notused1 = NULL; notused1 = NULL;
notused3 = 0; notused2 = 0;
notused4 = NULL; notused3 = NULL;
if ((ret = __ham_newpage_read(dbtp->data, &argp)) != 0) if ((ret = __ham_newpage_read(dbtp->data, &argp)) != 0)
return (ret); return (ret);
@ -462,7 +462,7 @@ int __ham_splitmeta_log(logp, txnid, ret_lsnp, flags,
else else
memset(bp, 0, sizeof(*metalsn)); memset(bp, 0, sizeof(*metalsn));
bp += sizeof(*metalsn); bp += sizeof(*metalsn);
#ifdef DEBUG #ifdef DIAGNOSTIC
if ((u_int32_t)(bp - (u_int8_t *)logrec.data) != logrec.size) if ((u_int32_t)(bp - (u_int8_t *)logrec.data) != logrec.size)
fprintf(stderr, "Error in log record length"); fprintf(stderr, "Error in log record length");
#endif #endif
@ -478,22 +478,23 @@ int __ham_splitmeta_log(logp, txnid, ret_lsnp, flags,
* PUBLIC: __P((DB_LOG *, DBT *, DB_LSN *, int, void *)); * PUBLIC: __P((DB_LOG *, DBT *, DB_LSN *, int, void *));
*/ */
int int
__ham_splitmeta_print(notused1, dbtp, lsnp, notused3, notused4) __ham_splitmeta_print(notused1, dbtp, lsnp, notused2, notused3)
DB_LOG *notused1; DB_LOG *notused1;
DBT *dbtp; DBT *dbtp;
DB_LSN *lsnp; DB_LSN *lsnp;
int notused3; int notused2;
void *notused4; void *notused3;
{ {
__ham_splitmeta_args *argp; __ham_splitmeta_args *argp;
u_int32_t i; u_int32_t i;
int c, ret; u_int ch;
int ret;
i = 0; i = 0;
c = 0; ch = 0;
notused1 = NULL; notused1 = NULL;
notused3 = 0; notused2 = 0;
notused4 = NULL; notused3 = NULL;
if ((ret = __ham_splitmeta_read(dbtp->data, &argp)) != 0) if ((ret = __ham_splitmeta_read(dbtp->data, &argp)) != 0)
return (ret); return (ret);
@ -622,7 +623,7 @@ int __ham_splitdata_log(logp, txnid, ret_lsnp, flags,
else else
memset(bp, 0, sizeof(*pagelsn)); memset(bp, 0, sizeof(*pagelsn));
bp += sizeof(*pagelsn); bp += sizeof(*pagelsn);
#ifdef DEBUG #ifdef DIAGNOSTIC
if ((u_int32_t)(bp - (u_int8_t *)logrec.data) != logrec.size) if ((u_int32_t)(bp - (u_int8_t *)logrec.data) != logrec.size)
fprintf(stderr, "Error in log record length"); fprintf(stderr, "Error in log record length");
#endif #endif
@ -638,22 +639,23 @@ int __ham_splitdata_log(logp, txnid, ret_lsnp, flags,
* PUBLIC: __P((DB_LOG *, DBT *, DB_LSN *, int, void *)); * PUBLIC: __P((DB_LOG *, DBT *, DB_LSN *, int, void *));
*/ */
int int
__ham_splitdata_print(notused1, dbtp, lsnp, notused3, notused4) __ham_splitdata_print(notused1, dbtp, lsnp, notused2, notused3)
DB_LOG *notused1; DB_LOG *notused1;
DBT *dbtp; DBT *dbtp;
DB_LSN *lsnp; DB_LSN *lsnp;
int notused3; int notused2;
void *notused4; void *notused3;
{ {
__ham_splitdata_args *argp; __ham_splitdata_args *argp;
u_int32_t i; u_int32_t i;
int c, ret; u_int ch;
int ret;
i = 0; i = 0;
c = 0; ch = 0;
notused1 = NULL; notused1 = NULL;
notused3 = 0; notused2 = 0;
notused4 = NULL; notused3 = NULL;
if ((ret = __ham_splitdata_read(dbtp->data, &argp)) != 0) if ((ret = __ham_splitdata_read(dbtp->data, &argp)) != 0)
return (ret); return (ret);
@ -669,11 +671,11 @@ __ham_splitdata_print(notused1, dbtp, lsnp, notused3, notused4)
printf("\tpgno: %lu\n", (u_long)argp->pgno); printf("\tpgno: %lu\n", (u_long)argp->pgno);
printf("\tpageimage: "); printf("\tpageimage: ");
for (i = 0; i < argp->pageimage.size; i++) { for (i = 0; i < argp->pageimage.size; i++) {
c = ((char *)argp->pageimage.data)[i]; ch = ((u_int8_t *)argp->pageimage.data)[i];
if (isprint(c) || c == 0xa) if (isprint(ch) || ch == 0xa)
putchar(c); putchar(ch);
else else
printf("%#x ", c); printf("%#x ", ch);
} }
printf("\n"); printf("\n");
printf("\tpagelsn: [%lu][%lu]\n", printf("\tpagelsn: [%lu][%lu]\n",
@ -813,7 +815,7 @@ int __ham_replace_log(logp, txnid, ret_lsnp, flags,
} }
memcpy(bp, &makedup, sizeof(makedup)); memcpy(bp, &makedup, sizeof(makedup));
bp += sizeof(makedup); bp += sizeof(makedup);
#ifdef DEBUG #ifdef DIAGNOSTIC
if ((u_int32_t)(bp - (u_int8_t *)logrec.data) != logrec.size) if ((u_int32_t)(bp - (u_int8_t *)logrec.data) != logrec.size)
fprintf(stderr, "Error in log record length"); fprintf(stderr, "Error in log record length");
#endif #endif
@ -829,22 +831,23 @@ int __ham_replace_log(logp, txnid, ret_lsnp, flags,
* PUBLIC: __P((DB_LOG *, DBT *, DB_LSN *, int, void *)); * PUBLIC: __P((DB_LOG *, DBT *, DB_LSN *, int, void *));
*/ */
int int
__ham_replace_print(notused1, dbtp, lsnp, notused3, notused4) __ham_replace_print(notused1, dbtp, lsnp, notused2, notused3)
DB_LOG *notused1; DB_LOG *notused1;
DBT *dbtp; DBT *dbtp;
DB_LSN *lsnp; DB_LSN *lsnp;
int notused3; int notused2;
void *notused4; void *notused3;
{ {
__ham_replace_args *argp; __ham_replace_args *argp;
u_int32_t i; u_int32_t i;
int c, ret; u_int ch;
int ret;
i = 0; i = 0;
c = 0; ch = 0;
notused1 = NULL; notused1 = NULL;
notused3 = 0; notused2 = 0;
notused4 = NULL; notused3 = NULL;
if ((ret = __ham_replace_read(dbtp->data, &argp)) != 0) if ((ret = __ham_replace_read(dbtp->data, &argp)) != 0)
return (ret); return (ret);
@ -863,20 +866,20 @@ __ham_replace_print(notused1, dbtp, lsnp, notused3, notused4)
printf("\toff: %ld\n", (long)argp->off); printf("\toff: %ld\n", (long)argp->off);
printf("\tolditem: "); printf("\tolditem: ");
for (i = 0; i < argp->olditem.size; i++) { for (i = 0; i < argp->olditem.size; i++) {
c = ((char *)argp->olditem.data)[i]; ch = ((u_int8_t *)argp->olditem.data)[i];
if (isprint(c) || c == 0xa) if (isprint(ch) || ch == 0xa)
putchar(c); putchar(ch);
else else
printf("%#x ", c); printf("%#x ", ch);
} }
printf("\n"); printf("\n");
printf("\tnewitem: "); printf("\tnewitem: ");
for (i = 0; i < argp->newitem.size; i++) { for (i = 0; i < argp->newitem.size; i++) {
c = ((char *)argp->newitem.data)[i]; ch = ((u_int8_t *)argp->newitem.data)[i];
if (isprint(c) || c == 0xa) if (isprint(ch) || ch == 0xa)
putchar(c); putchar(ch);
else else
printf("%#x ", c); printf("%#x ", ch);
} }
printf("\n"); printf("\n");
printf("\tmakedup: %lu\n", (u_long)argp->makedup); printf("\tmakedup: %lu\n", (u_long)argp->makedup);
@ -1014,7 +1017,7 @@ int __ham_newpgno_log(logp, txnid, ret_lsnp, flags,
else else
memset(bp, 0, sizeof(*metalsn)); memset(bp, 0, sizeof(*metalsn));
bp += sizeof(*metalsn); bp += sizeof(*metalsn);
#ifdef DEBUG #ifdef DIAGNOSTIC
if ((u_int32_t)(bp - (u_int8_t *)logrec.data) != logrec.size) if ((u_int32_t)(bp - (u_int8_t *)logrec.data) != logrec.size)
fprintf(stderr, "Error in log record length"); fprintf(stderr, "Error in log record length");
#endif #endif
@ -1030,22 +1033,23 @@ int __ham_newpgno_log(logp, txnid, ret_lsnp, flags,
* PUBLIC: __P((DB_LOG *, DBT *, DB_LSN *, int, void *)); * PUBLIC: __P((DB_LOG *, DBT *, DB_LSN *, int, void *));
*/ */
int int
__ham_newpgno_print(notused1, dbtp, lsnp, notused3, notused4) __ham_newpgno_print(notused1, dbtp, lsnp, notused2, notused3)
DB_LOG *notused1; DB_LOG *notused1;
DBT *dbtp; DBT *dbtp;
DB_LSN *lsnp; DB_LSN *lsnp;
int notused3; int notused2;
void *notused4; void *notused3;
{ {
__ham_newpgno_args *argp; __ham_newpgno_args *argp;
u_int32_t i; u_int32_t i;
int c, ret; u_int ch;
int ret;
i = 0; i = 0;
c = 0; ch = 0;
notused1 = NULL; notused1 = NULL;
notused3 = 0; notused2 = 0;
notused4 = NULL; notused3 = NULL;
if ((ret = __ham_newpgno_read(dbtp->data, &argp)) != 0) if ((ret = __ham_newpgno_read(dbtp->data, &argp)) != 0)
return (ret); return (ret);
@ -1182,7 +1186,7 @@ int __ham_ovfl_log(logp, txnid, ret_lsnp, flags,
else else
memset(bp, 0, sizeof(*metalsn)); memset(bp, 0, sizeof(*metalsn));
bp += sizeof(*metalsn); bp += sizeof(*metalsn);
#ifdef DEBUG #ifdef DIAGNOSTIC
if ((u_int32_t)(bp - (u_int8_t *)logrec.data) != logrec.size) if ((u_int32_t)(bp - (u_int8_t *)logrec.data) != logrec.size)
fprintf(stderr, "Error in log record length"); fprintf(stderr, "Error in log record length");
#endif #endif
@ -1198,22 +1202,23 @@ int __ham_ovfl_log(logp, txnid, ret_lsnp, flags,
* PUBLIC: __P((DB_LOG *, DBT *, DB_LSN *, int, void *)); * PUBLIC: __P((DB_LOG *, DBT *, DB_LSN *, int, void *));
*/ */
int int
__ham_ovfl_print(notused1, dbtp, lsnp, notused3, notused4) __ham_ovfl_print(notused1, dbtp, lsnp, notused2, notused3)
DB_LOG *notused1; DB_LOG *notused1;
DBT *dbtp; DBT *dbtp;
DB_LSN *lsnp; DB_LSN *lsnp;
int notused3; int notused2;
void *notused4; void *notused3;
{ {
__ham_ovfl_args *argp; __ham_ovfl_args *argp;
u_int32_t i; u_int32_t i;
int c, ret; u_int ch;
int ret;
i = 0; i = 0;
c = 0; ch = 0;
notused1 = NULL; notused1 = NULL;
notused3 = 0; notused2 = 0;
notused4 = NULL; notused3 = NULL;
if ((ret = __ham_ovfl_read(dbtp->data, &argp)) != 0) if ((ret = __ham_ovfl_read(dbtp->data, &argp)) != 0)
return (ret); return (ret);
@ -1364,7 +1369,7 @@ int __ham_copypage_log(logp, txnid, ret_lsnp, flags,
memcpy(bp, page->data, page->size); memcpy(bp, page->data, page->size);
bp += page->size; bp += page->size;
} }
#ifdef DEBUG #ifdef DIAGNOSTIC
if ((u_int32_t)(bp - (u_int8_t *)logrec.data) != logrec.size) if ((u_int32_t)(bp - (u_int8_t *)logrec.data) != logrec.size)
fprintf(stderr, "Error in log record length"); fprintf(stderr, "Error in log record length");
#endif #endif
@ -1380,22 +1385,23 @@ int __ham_copypage_log(logp, txnid, ret_lsnp, flags,
* PUBLIC: __P((DB_LOG *, DBT *, DB_LSN *, int, void *)); * PUBLIC: __P((DB_LOG *, DBT *, DB_LSN *, int, void *));
*/ */
int int
__ham_copypage_print(notused1, dbtp, lsnp, notused3, notused4) __ham_copypage_print(notused1, dbtp, lsnp, notused2, notused3)
DB_LOG *notused1; DB_LOG *notused1;
DBT *dbtp; DBT *dbtp;
DB_LSN *lsnp; DB_LSN *lsnp;
int notused3; int notused2;
void *notused4; void *notused3;
{ {
__ham_copypage_args *argp; __ham_copypage_args *argp;
u_int32_t i; u_int32_t i;
int c, ret; u_int ch;
int ret;
i = 0; i = 0;
c = 0; ch = 0;
notused1 = NULL; notused1 = NULL;
notused3 = 0; notused2 = 0;
notused4 = NULL; notused3 = NULL;
if ((ret = __ham_copypage_read(dbtp->data, &argp)) != 0) if ((ret = __ham_copypage_read(dbtp->data, &argp)) != 0)
return (ret); return (ret);
@ -1418,11 +1424,11 @@ __ham_copypage_print(notused1, dbtp, lsnp, notused3, notused4)
(u_long)argp->nnextlsn.file, (u_long)argp->nnextlsn.offset); (u_long)argp->nnextlsn.file, (u_long)argp->nnextlsn.offset);
printf("\tpage: "); printf("\tpage: ");
for (i = 0; i < argp->page.size; i++) { for (i = 0; i < argp->page.size; i++) {
c = ((char *)argp->page.data)[i]; ch = ((u_int8_t *)argp->page.data)[i];
if (isprint(c) || c == 0xa) if (isprint(ch) || ch == 0xa)
putchar(c); putchar(ch);
else else
printf("%#x ", c); printf("%#x ", ch);
} }
printf("\n"); printf("\n");
printf("\n"); printf("\n");

View File

@ -1,13 +1,13 @@
/*- /*-
* See the file LICENSE for redistribution information. * See the file LICENSE for redistribution information.
* *
* Copyright (c) 1996, 1997 * Copyright (c) 1996, 1997, 1998
* Sleepycat Software. All rights reserved. * Sleepycat Software. All rights reserved.
*/ */
#include "config.h" #include "config.h"
#ifndef lint #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 */ #endif /* not lint */
#ifndef NO_SYSTEM_INCLUDES #ifndef NO_SYSTEM_INCLUDES

View File

@ -1,7 +1,7 @@
/*- /*-
* See the file LICENSE for redistribution information. * See the file LICENSE for redistribution information.
* *
* Copyright (c) 1996, 1997 * Copyright (c) 1996, 1997, 1998
* Sleepycat Software. All rights reserved. * Sleepycat Software. All rights reserved.
*/ */
/* /*
@ -43,7 +43,7 @@
#include "config.h" #include "config.h"
#ifndef lint #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 */ #endif /* not lint */
#ifdef DEBUG #ifdef DEBUG
@ -60,9 +60,6 @@ static const char sccsid[] = "@(#)hash_debug.c 10.2 (Sleepycat) 6/21/97";
*/ */
#ifndef NO_SYSTEM_INCLUDES #ifndef NO_SYSTEM_INCLUDES
#include <sys/types.h> #include <sys/types.h>
#include <stdio.h>
#include <string.h>
#endif #endif
#include "db_int.h" #include "db_int.h"
@ -83,10 +80,9 @@ __ham_dump_bucket(hashp, bucket)
{ {
PAGE *p; PAGE *p;
db_pgno_t pgno; db_pgno_t pgno;
int ret;
for (pgno = BUCKET_TO_PAGE(hashp, bucket); pgno != PGNO_INVALID;) { 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; break;
(void)__db_prpage(p, 1); (void)__db_prpage(p, 1);
pgno = p->next_pgno; pgno = p->next_pgno;

View File

@ -1,7 +1,7 @@
/*- /*-
* See the file LICENSE for redistribution information. * See the file LICENSE for redistribution information.
* *
* Copyright (c) 1996, 1997 * Copyright (c) 1996, 1997, 1998
* Sleepycat Software. All rights reserved. * Sleepycat Software. All rights reserved.
*/ */
/* /*
@ -42,7 +42,7 @@
#include "config.h" #include "config.h"
#ifndef lint #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 */ #endif /* not lint */
/* /*
@ -61,15 +61,11 @@ static const char sccsid[] = "@(#)hash_dup.c 10.10 (Sleepycat) 1/8/98";
#ifndef NO_SYSTEM_INCLUDES #ifndef NO_SYSTEM_INCLUDES
#include <sys/types.h> #include <sys/types.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h> #include <string.h>
#include <unistd.h>
#endif #endif
#include "db_int.h" #include "db_int.h"
#include "db_page.h" #include "db_page.h"
#include "db_swap.h"
#include "hash.h" #include "hash.h"
static int __ham_check_move __P((HTAB *, HASH_CURSOR *, int32_t)); 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 * Case 4: The element is large enough to push the duplicate set onto a
* separate page. * 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 int
__ham_add_dup(hashp, hcp, nval, flags) __ham_add_dup(hashp, hcp, nval, flags)
HTAB *hashp; HTAB *hashp;
HASH_CURSOR *hcp; HASH_CURSOR *hcp;
DBT *nval; DBT *nval;
int flags; u_int32_t flags;
{ {
DBT pval, tmp_val; DBT pval, tmp_val;
u_int32_t del_len, new_size; u_int32_t del_len, new_size;
@ -367,9 +363,9 @@ __ham_check_move(hashp, hcp, add_len)
DB_LSN new_lsn; DB_LSN new_lsn;
PAGE *next_pagep; PAGE *next_pagep;
db_pgno_t next_pgno; db_pgno_t next_pgno;
int rectype, ret; u_int32_t new_datalen, old_len, rectype;
u_int32_t new_datalen, old_len;
u_int8_t *hk; u_int8_t *hk;
int ret;
/* /*
* Check if we can do whatever we need to on this page. If not, * 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) (ret = __ham_put_page(hashp->dbp, next_pagep, 0)) != 0)
return (ret); 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); return (ret);
if (P_FREESPACE(next_pagep) >= new_datalen) if (P_FREESPACE(next_pagep) >= new_datalen)

View File

@ -1,7 +1,7 @@
/*- /*-
* See the file LICENSE for redistribution information. * See the file LICENSE for redistribution information.
* *
* Copyright (c) 1996, 1997 * Copyright (c) 1996, 1997, 1998
* Sleepycat Software. All rights reserved. * Sleepycat Software. All rights reserved.
*/ */
/* /*
@ -47,7 +47,7 @@
#include "config.h" #include "config.h"
#ifndef lint #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 */ #endif /* not lint */
#ifndef NO_SYSTEM_INCLUDES #ifndef NO_SYSTEM_INCLUDES

View File

@ -1,7 +1,7 @@
/*- /*-
* See the file LICENSE for redistribution information. * See the file LICENSE for redistribution information.
* *
* Copyright (c) 1996, 1997 * Copyright (c) 1996, 1997, 1998
* Sleepycat Software. All rights reserved. * Sleepycat Software. All rights reserved.
*/ */
/* /*
@ -47,7 +47,7 @@
#include "config.h" #include "config.h"
#ifndef lint #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 */ #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 <sys/types.h>
#include <errno.h> #include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h> #include <string.h>
#include <unistd.h>
#endif #endif
#include "db_int.h" #include "db_int.h"
#include "db_page.h" #include "db_page.h"
#include "db_swap.h"
#include "hash.h" #include "hash.h"
static int __ham_lock_bucket __P((DB *, HASH_CURSOR *, db_lockmode_t)); 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); F_SET(cursorp, H_OK);
return (__ham_item_prev(hashp, cursorp, mode)); return (__ham_item_prev(hashp, cursorp, mode));
} }
/* /*
* PUBLIC: int __ham_item_first __P((HTAB *, HASH_CURSOR *, db_lockmode_t)); * 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, * __ham_item_prev --
* just returns the page number and index of the bigkey pointer pair. * 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)); * 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; 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)); * 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 * XXX
* just remove the pair. * 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 int
__ham_del_pair(hashp, cursorp, reclaim_page) __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. * Cursor is advanced to the beginning of the next page.
*/ */
cursorp->bndx = NDX_INVALID; cursorp->bndx = 0;
cursorp->pgno = PGNO(p); cursorp->pgno = PGNO(p);
F_SET(cursorp, H_DELETED);
chg_pgno = PGNO(p); chg_pgno = PGNO(p);
if ((ret = __ham_dirty_page(hashp, p)) != 0 || if ((ret = __ham_dirty_page(hashp, p)) != 0 ||
(ret = __ham_del_page(hashp->dbp, n_pagep)) != 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; DBT old_dbt, tdata, tmp;
DB_LSN new_lsn; DB_LSN new_lsn;
int32_t change; /* XXX: Possible overflow. */
u_int32_t len; u_int32_t len;
int32_t change;
int is_big, ret, type; int is_big, ret, type;
u_int8_t *beg, *dest, *end, *hk, *src; 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; 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. * Case 3 -- two subcases.
* A. This is not really a partial operation, but an overwrite. * A. This is not really a partial operation, but an overwrite.
@ -954,7 +1003,7 @@ __ham_split_page(hashp, obucket, nbucket)
HTAB *hashp; HTAB *hashp;
u_int32_t obucket, nbucket; u_int32_t obucket, nbucket;
{ {
DBT key, val, page_dbt; DBT key, page_dbt;
DB_ENV *dbenv; DB_ENV *dbenv;
DB_LSN new_lsn; DB_LSN new_lsn;
PAGE **pp, *old_pagep, *temp_pagep, *new_pagep; PAGE **pp, *old_pagep, *temp_pagep, *new_pagep;
@ -995,7 +1044,7 @@ __ham_split_page(hashp, obucket, nbucket)
big_len = 0; big_len = 0;
big_buf = NULL; big_buf = NULL;
val.flags = key.flags = 0; key.flags = 0;
while (temp_pagep != NULL) { while (temp_pagep != NULL) {
for (n = 0; n < (db_indx_t)H_NUMPAIRS(temp_pagep); n++) { for (n = 0; n < (db_indx_t)H_NUMPAIRS(temp_pagep); n++) {
if ((ret = if ((ret =
@ -1103,8 +1152,8 @@ __ham_split_page(hashp, obucket, nbucket)
ret == 0) ret == 0)
ret = tret; ret = tret;
err: if (0) { if (0) {
if (old_pagep != NULL) err: if (old_pagep != NULL)
(void)__ham_put_page(hashp->dbp, old_pagep, 1); (void)__ham_put_page(hashp->dbp, old_pagep, 1);
if (new_pagep != NULL) if (new_pagep != NULL)
(void)__ham_put_page(hashp->dbp, new_pagep, 1); (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 * to which we just added something. This allows us to link overflow
* pages and return the new page having correctly put the last page. * 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 __ham_add_el
* PUBLIC: int)); * PUBLIC: __P((HTAB *, HASH_CURSOR *, const DBT *, const DBT *, int));
*/ */
int int
__ham_add_el(hashp, hcp, key, val, type) __ham_add_el(hashp, hcp, key, val, type)
@ -1136,8 +1185,8 @@ __ham_add_el(hashp, hcp, key, val, type)
DB_LSN new_lsn; DB_LSN new_lsn;
HOFFPAGE doff, koff; HOFFPAGE doff, koff;
db_pgno_t next_pgno; db_pgno_t next_pgno;
u_int32_t data_size, key_size, pairsize; u_int32_t data_size, key_size, pairsize, rectype;
int do_expand, is_keybig, is_databig, rectype, ret; int do_expand, is_keybig, is_databig, ret;
int key_type, data_type; int key_type, data_type;
do_expand = 0; 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, * 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 * H_DUPLICATE, H_OFFDUP). Since we log splits at a high level, we
* do not need to do any logging here. * 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 void
__ham_copy_item(hashp, src_page, src_ndx, dest_page) __ham_copy_item(hashp, src_page, src_ndx, dest_page)
HTAB *hashp; HTAB *hashp;
PAGE *src_page; PAGE *src_page;
int src_ndx; u_int32_t src_ndx;
PAGE *dest_page; PAGE *dest_page;
{ {
u_int32_t len; u_int32_t len;
@ -1409,7 +1459,7 @@ __ham_del_page(dbp, pagep)
LSN(pagep) = new_lsn; LSN(pagep) = new_lsn;
} }
#ifdef DEBUG #ifdef DIAGNOSTIC
{ {
db_pgno_t __pgno; db_pgno_t __pgno;
DB_LSN __lsn; DB_LSN __lsn;
@ -1563,13 +1613,13 @@ __ham_overflow_page(dbp, type, pp)
#ifdef DEBUG #ifdef DEBUG
/* /*
* PUBLIC: #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 * PUBLIC: #endif
*/ */
int db_pgno_t
__bucket_to_page(hashp, n) __bucket_to_page(hashp, n)
HTAB *hashp; HTAB *hashp;
int n; db_pgno_t n;
{ {
int ret_val; int ret_val;
@ -1580,7 +1630,6 @@ __bucket_to_page(hashp, n)
} }
#endif #endif
/* /*
* Create a bunch of overflow pages at the current split point. * Create a bunch of overflow pages at the current split point.
* PUBLIC: void __ham_init_ovflpages __P((HTAB *)); * 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. * 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 * If the flag is set to H_ISDUP, then we are talking about the
* duplicate page, not the main page. * 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 int
__ham_next_cpage(hashp, hcp, pgno, dirty, flags) __ham_next_cpage(hashp, hcp, pgno, dirty, flags)
@ -1669,22 +1719,22 @@ __ham_next_cpage(hashp, hcp, pgno, dirty, flags)
HASH_CURSOR *hcp; HASH_CURSOR *hcp;
db_pgno_t pgno; db_pgno_t pgno;
int dirty; int dirty;
int flags; u_int32_t flags;
{ {
PAGE *p; PAGE *p;
int ret; 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) (ret = __ham_put_page(hashp->dbp, hcp->dpagep, dirty)) != 0)
return (ret); 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) (ret = __ham_put_page(hashp->dbp, hcp->pagep, dirty)) != 0)
return (ret); return (ret);
if ((ret = __ham_get_page(hashp->dbp, pgno, &p)) != 0) if ((ret = __ham_get_page(hashp->dbp, pgno, &p)) != 0)
return (ret); return (ret);
if (flags & H_ISDUP) { if (LF_ISSET(H_ISDUP)) {
hcp->dpagep = p; hcp->dpagep = p;
hcp->dpgno = pgno; hcp->dpgno = pgno;
hcp->dndx = 0; hcp->dndx = 0;

View File

@ -1,7 +1,7 @@
/*- /*-
* See the file LICENSE for redistribution information. * See the file LICENSE for redistribution information.
* *
* Copyright (c) 1996, 1997 * Copyright (c) 1996, 1997, 1998
* Sleepycat Software. All rights reserved. * Sleepycat Software. All rights reserved.
*/ */
/* /*
@ -47,14 +47,13 @@
#include "config.h" #include "config.h"
#ifndef lint #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 */ #endif /* not lint */
#ifndef NO_SYSTEM_INCLUDES #ifndef NO_SYSTEM_INCLUDES
#include <sys/types.h> #include <sys/types.h>
#include <errno.h> #include <errno.h>
#include <stdlib.h>
#include <string.h> #include <string.h>
#endif #endif
@ -64,7 +63,6 @@ static const char sccsid[] = "@(#)hash_rec.c 10.15 (Sleepycat) 12/4/97";
#include "hash.h" #include "hash.h"
#include "btree.h" #include "btree.h"
#include "log.h" #include "log.h"
#include "db_dispatch.h"
#include "common_ext.h" #include "common_ext.h"
/* /*
@ -131,13 +129,23 @@ __ham_insdel_recover(logp, dbtp, lsnp, redo, info)
if ((op == DELPAIR && cmp_n == 0 && !redo) || if ((op == DELPAIR && cmp_n == 0 && !redo) ||
(op == PUTPAIR && cmp_p == 0 && redo)) { (op == PUTPAIR && cmp_p == 0 && redo)) {
/* Need to redo a PUT or undo a delete. */ /*
__ham_putitem(pagep, &argp->key, * Need to redo a PUT or undo a delete. If we are undoing a
!redo || PAIR_ISKEYBIG(argp->opcode) ? * delete, we've got to restore the item back to its original
H_OFFPAGE : H_KEYDATA); * position. That's a royal pain in the butt (because we do
__ham_putitem(pagep, &argp->data, * not store item lengths on the page), but there's no choice.
!redo || PAIR_ISDATABIG(argp->opcode) ? */
H_OFFPAGE : H_KEYDATA); 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; LSN(pagep) = redo ? *lsnp : argp->pagelsn;
if ((ret = __ham_put_page(file_dbp, pagep, 1)) != 0) if ((ret = __ham_put_page(file_dbp, pagep, 1)) != 0)
@ -453,7 +461,7 @@ __ham_newpgno_recover(logp, dbtp, lsnp, redo, info)
DBT *dbtp; DBT *dbtp;
DB_LSN *lsnp; DB_LSN *lsnp;
int redo; int redo;
void *info; void *info;
{ {
__ham_newpgno_args *argp; __ham_newpgno_args *argp;
DB *mdbp, *file_dbp; DB *mdbp, *file_dbp;
@ -574,7 +582,7 @@ __ham_splitmeta_recover(logp, dbtp, lsnp, redo, info)
DBT *dbtp; DBT *dbtp;
DB_LSN *lsnp; DB_LSN *lsnp;
int redo; int redo;
void *info; void *info;
{ {
__ham_splitmeta_args *argp; __ham_splitmeta_args *argp;
DB *mdbp, *file_dbp; DB *mdbp, *file_dbp;
@ -649,7 +657,7 @@ __ham_splitdata_recover(logp, dbtp, lsnp, redo, info)
DBT *dbtp; DBT *dbtp;
DB_LSN *lsnp; DB_LSN *lsnp;
int redo; int redo;
void *info; void *info;
{ {
__ham_splitdata_args *argp; __ham_splitdata_args *argp;
DB *mdbp, *file_dbp; DB *mdbp, *file_dbp;

View File

@ -1,14 +1,14 @@
/*- /*-
* See the file LICENSE for redistribution information. * See the file LICENSE for redistribution information.
* *
* Copyright (c) 1996, 1997 * Copyright (c) 1996, 1997, 1998
* Sleepycat Software. All rights reserved. * Sleepycat Software. All rights reserved.
*/ */
#include "config.h" #include "config.h"
#ifndef lint #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 */ #endif /* not lint */
#ifndef NO_SYSTEM_INCLUDES #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_int.h"
#include "db_page.h" #include "db_page.h"
#include "hash.h" #include "hash.h"
#include "common_ext.h"
/* /*
* __ham_stat -- * __ham_stat --

View File

@ -1,7 +1,7 @@
/*- /*-
* See the file LICENSE for redistribution information. * See the file LICENSE for redistribution information.
* *
* Copyright (c) 1996, 1997 * Copyright (c) 1996, 1997, 1998
* Sleepycat Software. All rights reserved. * Sleepycat Software. All rights reserved.
*/ */
/* /*
@ -43,7 +43,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE. * SUCH DAMAGE.
* *
* @(#)btree.h 10.17 (Sleepycat) 9/23/97 * @(#)btree.h 10.21 (Sleepycat) 5/23/98
*/ */
/* Forward structure declarations. */ /* Forward structure declarations. */
@ -103,28 +103,39 @@ struct __recno; typedef struct __recno RECNO;
* to return deleted entries. To simplify both the mnemonic representation * to return deleted entries. To simplify both the mnemonic representation
* and the code that checks for various cases, we construct a set of bitmasks. * and the code that checks for various cases, we construct a set of bitmasks.
*/ */
#define S_READ 0x0001 /* Read locks. */ #define S_READ 0x00001 /* Read locks. */
#define S_WRITE 0x0002 /* Write locks. */ #define S_WRITE 0x00002 /* Write locks. */
#define S_APPEND 0x0040 /* Append to the tree. */ #define S_APPEND 0x00040 /* Append to the tree. */
#define S_DELNO 0x0080 /* Don't return deleted items. */ #define S_DELNO 0x00080 /* Don't return deleted items. */
#define S_DUPFIRST 0x0100 /* Return first duplicate. */ #define S_DUPFIRST 0x00100 /* Return first duplicate. */
#define S_DUPLAST 0x0200 /* Return last duplicate. */ #define S_DUPLAST 0x00200 /* Return last duplicate. */
#define S_EXACT 0x0400 /* Exact items only. */ #define S_EXACT 0x00400 /* Exact items only. */
#define S_PARENT 0x0800 /* Lock page pair. */ #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) #define S_DELETE (S_WRITE | S_DUPFIRST | S_DELNO | S_EXACT | S_STACK)
#define S_FIND (S_READ | S_DUPFIRST | S_DELNO) #define S_FIND (S_READ | S_DUPFIRST | S_DELNO)
#define S_INSERT (S_WRITE | S_DUPLAST) #define S_INSERT (S_WRITE | S_DUPLAST | S_STACK)
#define S_KEYFIRST (S_WRITE | S_DUPFIRST) #define S_KEYFIRST (S_WRITE | S_DUPFIRST | S_STACK)
#define S_KEYLAST (S_WRITE | S_DUPLAST) #define S_KEYLAST (S_WRITE | S_DUPLAST | S_STACK)
#define S_WRPAIR (S_WRITE | S_DUPLAST | S_PARENT) #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(). * Flags to __bam_iitem().
*/ */
#define BI_NEWKEY 0x01 /* New key. */ #define BI_DELETED 0x01 /* Key/data pair only placeholder. */
#define BI_DELETED 0x02 /* 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 * Various routines pass around page references. A page reference can be a
@ -137,6 +148,21 @@ struct __epg {
DB_LOCK lock; /* The page's lock. */ DB_LOCK lock; /* The page's lock. */
}; };
/*
* 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. * Btree cursor.
* *

View File

@ -2,7 +2,7 @@
#ifndef _btree_ext_h_ #ifndef _btree_ext_h_
#define _btree_ext_h_ #define _btree_ext_h_
int __bam_close __P((DB *)); 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_cmp __P((DB *, const DBT *, EPG *));
int __bam_defcmp __P((const DBT *, const DBT *)); int __bam_defcmp __P((const DBT *, const DBT *));
size_t __bam_defpfx __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_mswap __P((PAGE *));
int __bam_cursor __P((DB *, DB_TXN *, DBC **)); int __bam_cursor __P((DB *, DB_TXN *, DBC **));
int __bam_c_iclose __P((DB *, 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_ovfl_chk __P((DB *, CURSOR *, u_int32_t, int));
int __bam_cprint __P((DB *)); int __bam_cprint __P((DB *));
int __bam_ca_delete __P((DB *, db_pgno_t, u_int32_t, CURSOR *, int)); 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)); __P((DB *, db_pgno_t, u_int32_t, ca_replace_arg));
void __bam_ca_split __P((DB *, void __bam_ca_split __P((DB *,
db_pgno_t, db_pgno_t, db_pgno_t, u_int32_t, int)); db_pgno_t, db_pgno_t, db_pgno_t, u_int32_t, int));
int __bam_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 *, int)); int __ram_delete __P((DB *, DB_TXN *, DBT *, u_int32_t));
int __bam_ditem __P((DB *, PAGE *, 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_adjindx __P((DB *, PAGE *, u_int32_t, u_int32_t, int));
int __bam_dpage __P((DB *, const DBT *)); int __bam_dpage __P((DB *, const DBT *));
@ -35,10 +35,10 @@ int __bam_free __P((DB *, PAGE *));
int __bam_lt __P((DB *)); int __bam_lt __P((DB *));
int __bam_lget __P((DB *, int, db_pgno_t, db_lockmode_t, DB_LOCK *)); int __bam_lget __P((DB *, int, db_pgno_t, db_lockmode_t, DB_LOCK *));
int __bam_lput __P((DB *, DB_LOCK)); int __bam_lput __P((DB *, DB_LOCK));
int __bam_pget __P((DB *, PAGE **, db_pgno_t *, int)); int __bam_pget __P((DB *, PAGE **, db_pgno_t *, u_int32_t));
int __bam_put __P((DB *, DB_TXN *, DBT *, DBT *, int)); int __bam_put __P((DB *, DB_TXN *, DBT *, DBT *, u_int32_t));
int __bam_iitem __P((DB *, 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_ritem __P((DB *, PAGE *, u_int32_t, DBT *));
int __bam_pg_alloc_recover int __bam_pg_alloc_recover
__P((DB_LOG *, DBT *, DB_LSN *, int, void *)); __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_cprint __P((DB *));
int __ram_getno __P((DB *, const DBT *, db_recno_t *, int)); int __ram_getno __P((DB *, const DBT *, db_recno_t *, int));
int __ram_snapshot __P((DB *)); int __ram_snapshot __P((DB *));
int __bam_rsearch __P((DB *, db_recno_t *, u_int, int, int *)); int __bam_rsearch __P((DB *, db_recno_t *, u_int32_t, int, int *));
int __bam_adjust __P((DB *, BTREE *, int)); int __bam_adjust __P((DB *, BTREE *, int32_t));
int __bam_nrecs __P((DB *, db_recno_t *)); int __bam_nrecs __P((DB *, db_recno_t *));
db_recno_t __bam_total __P((PAGE *)); db_recno_t __bam_total __P((PAGE *));
int __bam_search __P((DB *, 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_stkrel __P((DB *));
int __bam_stkgrow __P((BTREE *)); int __bam_stkgrow __P((BTREE *));
int __bam_split __P((DB *, void *)); int __bam_split __P((DB *, void *));
int __bam_broot __P((DB *, PAGE *, PAGE *, PAGE *)); int __bam_broot __P((DB *, PAGE *, PAGE *, PAGE *));
int __ram_root __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_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 *)); void __bam_add_mstat __P((DB_BTREE_LSTAT *, DB_BTREE_LSTAT *));
int __bam_pg_alloc_log int __bam_pg_alloc_log
__P((DB_LOG *, DB_TXN *, DB_LSN *, u_int32_t, __P((DB_LOG *, DB_TXN *, DB_LSN *, u_int32_t,

View File

@ -53,9 +53,6 @@ int snprintf __P((char *, size_t, const char *, ...));
int snprintf(); int snprintf();
#endif #endif
#endif #endif
#ifndef HAVE_STRDUP
char *strdup __P((const char *));
#endif
#ifndef HAVE_STRERROR #ifndef HAVE_STRERROR
char *strerror __P((int)); char *strerror __P((int));
#endif #endif

View File

@ -2,8 +2,8 @@
#ifndef _common_ext_h_ #ifndef _common_ext_h_
#define _common_ext_h_ #define _common_ext_h_
int __db_appname __P((DB_ENV *, int __db_appname __P((DB_ENV *,
APPNAME, const char *, const char *, int *, char **)); APPNAME, const char *, const char *, u_int32_t, int *, char **));
int __db_apprec __P((DB_ENV *, int)); int __db_apprec __P((DB_ENV *, u_int32_t));
int __db_byteorder __P((DB_ENV *, int)); int __db_byteorder __P((DB_ENV *, int));
#ifdef __STDC__ #ifdef __STDC__
void __db_err __P((const DB_ENV *dbenv, const char *fmt, ...)); 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(); void __db_err();
#endif #endif
int __db_panic __P((DB *)); int __db_panic __P((DB *));
int __db_fchk __P((DB_ENV *, const char *, int, int)); int __db_fchk __P((DB_ENV *, const char *, u_int32_t, u_int32_t));
int __db_fcchk __P((DB_ENV *, const char *, int, int, int)); int __db_fcchk
int __db_cdelchk __P((const DB *, int, int, int)); __P((DB_ENV *, const char *, u_int32_t, u_int32_t, u_int32_t));
int __db_cgetchk __P((const DB *, DBT *, DBT *, int, int)); 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 *, int __db_cputchk __P((const DB *,
const DBT *, DBT *, int, int, int)); const DBT *, DBT *, u_int32_t, int, int));
int __db_delchk __P((const DB *, int, int)); int __db_delchk __P((const DB *, DBT *, u_int32_t, int));
int __db_getchk __P((const DB *, const DBT *, DBT *, int)); int __db_getchk __P((const DB *, const DBT *, DBT *, u_int32_t));
int __db_putchk __P((const DB *, DBT *, const DBT *, int, int, int)); int __db_putchk
int __db_statchk __P((const DB *, int)); __P((const DB *, DBT *, const DBT *, u_int32_t, int, int));
int __db_syncchk __P((const DB *, 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)); int __db_ferr __P((const DB_ENV *, const char *, int));
u_int32_t __db_log2 __P((u_int32_t)); u_int32_t __db_log2 __P((u_int32_t));
int __db_rcreate __P((DB_ENV *, APPNAME, int __db_rattach __P((REGINFO *));
const char *, const char *, int, size_t, int, int *, void *)); int __db_rdetach __P((REGINFO *));
int __db_rinit __P((DB_ENV *, RLAYOUT *, int, size_t, int)); int __db_runlink __P((REGINFO *, int));
int __db_ropen __P((DB_ENV *, int __db_rgrow __P((REGINFO *, size_t));
APPNAME, const char *, const char *, int, int *, void *)); int __db_rreattach __P((REGINFO *, size_t));
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 *));
void __db_shalloc_init __P((void *, size_t)); void __db_shalloc_init __P((void *, size_t));
int __db_shalloc __P((void *, size_t, size_t, void *)); int __db_shalloc __P((void *, size_t, size_t, void *));
void __db_shalloc_free __P((void *, void *)); void __db_shalloc_free __P((void *, void *));
size_t __db_shalloc_count __P((void *)); size_t __db_shalloc_count __P((void *));
size_t __db_shsizeof __P((void *)); size_t __db_shsizeof __P((void *));
void __db_shalloc_dump __P((FILE *, void *)); void __db_shalloc_dump __P((void *, FILE *));
int __db_tablesize __P((u_int)); int __db_tablesize __P((u_int32_t));
void __db_hashinit __P((void *, int)); void __db_hashinit __P((void *, u_int32_t));
#endif /* _common_ext_h_ */ #endif /* _common_ext_h_ */

View File

@ -1,10 +1,10 @@
/*- /*-
* See the file LICENSE for redistribution information. * See the file LICENSE for redistribution information.
* *
* Copyright (c) 1997 * Copyright (c) 1997, 1998
* Sleepycat Software. All rights reserved. * 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_ #ifndef _CXX_INT_H_

View File

@ -1,10 +1,10 @@
/*- /*-
* See the file LICENSE for redistribution information. * See the file LICENSE for redistribution information.
* *
* Copyright (c) 1996, 1997 * Copyright (c) 1996, 1997, 1998
* Sleepycat Software. All rights reserved. * 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_ #ifndef _DB_H_
@ -54,8 +54,7 @@
* *
* !!! * !!!
* We also provide the standard u_int, u_long etc., if they're not provided * 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 * by the system.
* need them.
*/ */
#ifndef __BIT_TYPES_DEFINED__ #ifndef __BIT_TYPES_DEFINED__
#define __BIT_TYPES_DEFINED__ #define __BIT_TYPES_DEFINED__
@ -72,9 +71,9 @@
@u_long_decl@ @u_long_decl@
#define DB_VERSION_MAJOR 2 #define DB_VERSION_MAJOR 2
#define DB_VERSION_MINOR 3 #define DB_VERSION_MINOR 4
#define DB_VERSION_PATCH 16 #define DB_VERSION_PATCH 14
#define DB_VERSION_STRING "Sleepycat Software: DB 2.3.16: (1/19/98)" #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_int32_t db_pgno_t; /* Page number type. */
typedef u_int16_t db_indx_t; /* Page offset 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_dbt; typedef struct __db_dbt DBT;
struct __db_env; typedef struct __db_env DB_ENV; struct __db_env; typedef struct __db_env DB_ENV;
struct __db_info; typedef struct __db_info DB_INFO; 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_lockregion; typedef struct __db_lockregion DB_LOCKREGION;
struct __db_lockreq; typedef struct __db_lockreq DB_LOCKREQ; struct __db_lockreq; typedef struct __db_lockreq DB_LOCKREQ;
struct __db_locktab; typedef struct __db_locktab DB_LOCKTAB; 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_log_stat; typedef struct __db_log_stat DB_LOG_STAT;
struct __db_lsn; typedef struct __db_lsn DB_LSN; struct __db_lsn; typedef struct __db_lsn DB_LSN;
struct __db_mpool; typedef struct __db_mpool DB_MPOOL; 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_fstat;typedef struct __db_mpool_fstat DB_MPOOL_FSTAT;
struct __db_mpool_stat; typedef struct __db_mpool_stat DB_MPOOL_STAT; struct __db_mpool_stat; typedef struct __db_mpool_stat DB_MPOOL_STAT;
struct __db_mpoolfile; typedef struct __db_mpoolfile DB_MPOOLFILE; 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 * 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. * 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_CLOSE 2 /* POSIX 1003.1 close. */
#define DB_FUNC_DIRFREE 3 /* DB: free directory list. */ #define DB_FUNC_DIRFREE 3 /* DB: free directory list. */
#define DB_FUNC_DIRLIST 4 /* DB: create 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_REALLOC 13 /* ANSI C realloc. */
#define DB_FUNC_SEEK 14 /* POSIX 1003.1 lseek. */ #define DB_FUNC_SEEK 14 /* POSIX 1003.1 lseek. */
#define DB_FUNC_SLEEP 15 /* DB: sleep secs/usecs. */ #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_UNLINK 17 /* POSIX 1003.1 unlink. */
#define DB_FUNC_UNMAP 18 /* DB: unmap shared memory file. */ #define DB_FUNC_UNMAP 18 /* DB: unmap shared memory file. */
#define DB_FUNC_WRITE 19 /* POSIX 1003.1 write. */ #define DB_FUNC_WRITE 19 /* POSIX 1003.1 write. */
#define DB_FUNC_YIELD 20 /* DB: yield thread to scheduler. */ #define DB_FUNC_YIELD 20 /* DB: yield thread to scheduler. */
#define DB_TSL_SPINS 21 /* DB: initialize spin count. */ #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. * Database configuration and initialization.
@ -162,52 +169,51 @@ struct __db_dbt {
/* /*
* Flags understood by both db_open(3) and db_appinit(3). * Flags understood by both db_open(3) and db_appinit(3).
*/ */
#define DB_CREATE 0x00001 /* O_CREAT: create file as necessary. */ #define DB_CREATE 0x000001 /* O_CREAT: create file as necessary. */
#define DB_NOMMAP 0x00002 /* Don't mmap underlying file. */ #define DB_NOMMAP 0x000002 /* Don't mmap underlying file. */
#define DB_THREAD 0x00004 /* Free-thread DB package handles. */ #define DB_THREAD 0x000004 /* Free-thread DB package handles. */
/* /*
* Flags understood by db_appinit(3). * Flags understood by db_appinit(3).
*
* DB_MUTEXDEBUG is internal only, and not documented.
*/ */
/* 0x00007 COMMON MASK. */ /* 0x000007 COMMON MASK. */
#define DB_INIT_LOCK 0x00008 /* Initialize locking. */ #define DB_INIT_LOCK 0x000008 /* Initialize locking. */
#define DB_INIT_LOG 0x00010 /* Initialize logging. */ #define DB_INIT_LOG 0x000010 /* Initialize logging. */
#define DB_INIT_MPOOL 0x00020 /* Initialize mpool. */ #define DB_INIT_MPOOL 0x000020 /* Initialize mpool. */
#define DB_INIT_TXN 0x00040 /* Initialize transactions. */ #define DB_INIT_TXN 0x000040 /* Initialize transactions. */
#define DB_MPOOL_PRIVATE 0x00080 /* Mpool: private memory pool. */ #define DB_MPOOL_PRIVATE 0x000080 /* Mpool: private memory pool. */
#define DB_MUTEXDEBUG 0x00100 /* Do not get/set mutexes in regions. */ #define __UNUSED_100 0x000100
#define DB_RECOVER 0x00200 /* Run normal recovery. */ #define DB_RECOVER 0x000200 /* Run normal recovery. */
#define DB_RECOVER_FATAL 0x00400 /* Run catastrophic recovery. */ #define DB_RECOVER_FATAL 0x000400 /* Run catastrophic recovery. */
#define DB_TXN_NOSYNC 0x00800 /* Do not sync log on commit. */ #define DB_TXN_NOSYNC 0x000800 /* Do not sync log on commit. */
#define DB_USE_ENVIRON 0x01000 /* Use the environment. */ #define DB_USE_ENVIRON 0x001000 /* Use the environment. */
#define DB_USE_ENVIRON_ROOT 0x02000 /* Use the environment if root. */ #define DB_USE_ENVIRON_ROOT 0x002000 /* Use the environment if root. */
/* CURRENTLY UNUSED LOCK FLAGS. */ /* CURRENTLY UNUSED LOCK FLAGS. */
#define DB_TXN_LOCK_2PL 0x00000 /* Two-phase locking. */ #define DB_TXN_LOCK_2PL 0x000000 /* Two-phase locking. */
#define DB_TXN_LOCK_OPTIMISTIC 0x00000 /* Optimistic locking. */ #define DB_TXN_LOCK_OPTIMIST 0x000000 /* Optimistic locking. */
#define DB_TXN_LOCK_MASK 0x00000 /* Lock flags mask. */ #define DB_TXN_LOCK_MASK 0x000000 /* Lock flags mask. */
/* CURRENTLY UNUSED LOG FLAGS. */ /* CURRENTLY UNUSED LOG FLAGS. */
#define DB_TXN_LOG_REDO 0x00000 /* Redo-only logging. */ #define DB_TXN_LOG_REDO 0x000000 /* Redo-only logging. */
#define DB_TXN_LOG_UNDO 0x00000 /* Undo-only logging. */ #define DB_TXN_LOG_UNDO 0x000000 /* Undo-only logging. */
#define DB_TXN_LOG_UNDOREDO 0x00000 /* Undo/redo write-ahead logging. */ #define DB_TXN_LOG_UNDOREDO 0x000000 /* Undo/redo write-ahead logging. */
#define DB_TXN_LOG_MASK 0x00000 /* Log flags mask. */ #define DB_TXN_LOG_MASK 0x000000 /* Log flags mask. */
/* /*
* Flags understood by db_open(3). * Flags understood by db_open(3).
* *
* DB_EXCL and DB_TEMPORARY are internal only, and not documented. * DB_EXCL and DB_TEMPORARY are internal only, and are not documented.
* DB_SEQUENTIAL is currently internal, but likely to be exported some day. * DB_SEQUENTIAL is currently internal, but may be exported some day.
*/ */
/* 0x00007 COMMON MASK. */ /* 0x000007 COMMON MASK. */
/* 0x07fff ALREADY USED. */ /* 0x003fff ALREADY USED. */
#define DB_EXCL 0x08000 /* O_EXCL: exclusive open. */ #define __UNUSED_4000 0x004000
#define DB_RDONLY 0x10000 /* O_RDONLY: read-only. */ #define DB_EXCL 0x008000 /* O_EXCL: exclusive open. */
#define DB_SEQUENTIAL 0x20000 /* Indicate sequential access. */ #define DB_RDONLY 0x010000 /* O_RDONLY: read-only. */
#define DB_TEMPORARY 0x40000 /* Remove on last close. */ #define DB_SEQUENTIAL 0x020000 /* Indicate sequential access. */
#define DB_TRUNCATE 0x80000 /* O_TRUNCATE: replace existing DB. */ #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 * Deadlock detector modes; used in the DBENV structure to configure the
@ -240,9 +246,9 @@ struct __db_env {
/* Locking. */ /* Locking. */
DB_LOCKTAB *lk_info; /* Return from lock_open(). */ DB_LOCKTAB *lk_info; /* Return from lock_open(). */
u_int8_t *lk_conflicts; /* Two dimensional conflict matrix. */ u_int8_t *lk_conflicts; /* Two dimensional conflict matrix. */
int lk_modes; /* Number of lock modes in table. */ u_int32_t lk_modes; /* Number of lock modes in table. */
u_int lk_max; /* Maximum number of locks. */ u_int32_t lk_max; /* Maximum number of locks. */
u_int32_t lk_detect; /* Deadlock detect on every conflict. */ u_int32_t lk_detect; /* Deadlock detect on all conflicts. */
/* Logging. */ /* Logging. */
DB_LOG *lg_info; /* Return from log_open(). */ DB_LOG *lg_info; /* Return from log_open(). */
@ -255,7 +261,7 @@ struct __db_env {
/* Transactions. */ /* Transactions. */
DB_TXNMGR *tx_info; /* Return from txn_open(). */ 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. */ int (*tx_recover) /* Dispatch function for recovery. */
__P((DB_LOG *, DBT *, DB_LSN *, int, void *)); __P((DB_LOG *, DBT *, DB_LSN *, int, void *));
@ -300,17 +306,17 @@ struct __db_info {
void *(*db_malloc) __P((size_t)); void *(*db_malloc) __P((size_t));
/* Btree access method. */ /* Btree access method. */
int bt_maxkey; /* Maximum keys per page. */ u_int32_t bt_maxkey; /* Maximum keys per page. */
int bt_minkey; /* Minimum keys per page. */ u_int32_t bt_minkey; /* Minimum keys per page. */
int (*bt_compare) /* Comparison function. */ int (*bt_compare) /* Comparison function. */
__P((const DBT *, const DBT *)); __P((const DBT *, const DBT *));
size_t (*bt_prefix) /* Prefix function. */ size_t (*bt_prefix) /* Prefix function. */
__P((const DBT *, const DBT *)); __P((const DBT *, const DBT *));
/* Hash access method. */ /* Hash access method. */
unsigned int h_ffactor; /* Fill factor. */ u_int32_t h_ffactor; /* Fill factor. */
unsigned int h_nelem; /* Number of elements. */ u_int32_t h_nelem; /* Number of elements. */
u_int32_t (*h_hash) /* Hash function. */ u_int32_t (*h_hash) /* Hash function. */
__P((const void *, u_int32_t)); __P((const void *, u_int32_t));
/* Recno access method. */ /* Recno access method. */
@ -353,6 +359,7 @@ struct __db_info {
#define DB_SET 0x010000 /* c_get(), log_get() */ #define DB_SET 0x010000 /* c_get(), log_get() */
#define DB_SET_RANGE 0x020000 /* c_get() */ #define DB_SET_RANGE 0x020000 /* c_get() */
#define DB_SET_RECNO 0x040000 /* c_get() */ #define DB_SET_RECNO 0x040000 /* c_get() */
#define DB_CURLSN 0x080000 /* log_put() */
/* /*
* DB (user visible) error return codes. * DB (user visible) error return codes.
@ -435,14 +442,14 @@ struct __db {
void *(*db_malloc) __P((size_t)); void *(*db_malloc) __P((size_t));
/* Functions. */ /* Functions. */
int (*close) __P((DB *, int)); int (*close) __P((DB *, u_int32_t));
int (*cursor) __P((DB *, DB_TXN *, DBC **)); 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 (*fd) __P((DB *, int *));
int (*get) __P((DB *, DB_TXN *, DBT *, DBT *, int)); int (*get) __P((DB *, DB_TXN *, DBT *, DBT *, u_int32_t));
int (*put) __P((DB *, DB_TXN *, DBT *, DBT *, int)); int (*put) __P((DB *, DB_TXN *, DBT *, DBT *, u_int32_t));
int (*stat) __P((DB *, void *, void *(*)(size_t), int)); int (*stat) __P((DB *, void *, void *(*)(size_t), u_int32_t));
int (*sync) __P((DB *, int)); int (*sync) __P((DB *, u_int32_t));
#define DB_AM_DUP 0x000001 /* DB_DUP (internal). */ #define DB_AM_DUP 0x000001 /* DB_DUP (internal). */
#define DB_AM_INMEM 0x000002 /* In-memory; no sync on close. */ #define DB_AM_INMEM 0x000002 /* In-memory; no sync on close. */
@ -483,9 +490,9 @@ struct __dbc {
void *internal; /* Access method private. */ void *internal; /* Access method private. */
int (*c_close) __P((DBC *)); int (*c_close) __P((DBC *));
int (*c_del) __P((DBC *, int)); int (*c_del) __P((DBC *, u_int32_t));
int (*c_get) __P((DBC *, DBT *, DBT *, int)); int (*c_get) __P((DBC *, DBT *, DBT *, u_int32_t));
int (*c_put) __P((DBC *, DBT *, DBT *, int)); int (*c_put) __P((DBC *, DBT *, DBT *, u_int32_t));
}; };
/* Btree/recno statistics structure. */ /* Btree/recno statistics structure. */
@ -524,10 +531,11 @@ struct __db_bt_stat {
#if defined(__cplusplus) #if defined(__cplusplus)
extern "C" { extern "C" {
#endif #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_appexit __P((DB_ENV *));
int db_jump_set __P((void *, int)); 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)); int db_value_set __P((int, int));
char *db_version __P((int *, int *, int *)); char *db_version __P((int *, int *, int *));
#if defined(__cplusplus) #if defined(__cplusplus)
@ -575,6 +583,21 @@ typedef enum {
DB_LOCK_IWR /* Intent to read and write. */ DB_LOCK_IWR /* Intent to read and write. */
} db_lockmode_t; } 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. */ /* Lock request structure. */
struct __db_lockreq { struct __db_lockreq {
db_lockop_t op; /* Operation. */ db_lockop_t op; /* Operation. */
@ -596,19 +619,38 @@ extern const u_int8_t db_rw_conflicts[];
#define DB_LOCK_RIW_N 6 #define DB_LOCK_RIW_N 6
extern const u_int8_t db_riw_conflicts[]; 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) #if defined(__cplusplus)
extern "C" { extern "C" {
#endif #endif
int lock_close __P((DB_LOCKTAB *)); 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 *, 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_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_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_unlink __P((const char *, int, DB_ENV *));
int lock_vec __P((DB_LOCKTAB *, 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) #if defined(__cplusplus)
} }
#endif #endif
@ -651,19 +693,21 @@ struct __db_log_stat {
u_int32_t st_region_nowait; /* Region lock granted without wait. */ 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_file; /* Current log file number. */
u_int32_t st_cur_offset; /* Current log file offset. */ 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) #if defined(__cplusplus)
extern "C" { extern "C" {
#endif #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_close __P((DB_LOG *));
int log_compare __P((const DB_LSN *, const DB_LSN *)); int log_compare __P((const DB_LSN *, const DB_LSN *));
int log_file __P((DB_LOG *, const DB_LSN *, char *, size_t)); int log_file __P((DB_LOG *, const DB_LSN *, char *, size_t));
int log_flush __P((DB_LOG *, const DB_LSN *)); int log_flush __P((DB_LOG *, const DB_LSN *));
int log_get __P((DB_LOG *, DB_LSN *, DBT *, int)); int log_get __P((DB_LOG *, DB_LSN *, DBT *, u_int32_t));
int log_open __P((const char *, int, int, DB_ENV *, DB_LOG **)); int log_open __P((const char *, u_int32_t, int, DB_ENV *, DB_LOG **));
int log_put __P((DB_LOG *, DB_LSN *, const DBT *, int)); 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_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_stat __P((DB_LOG *, DB_LOG_STAT **, void *(*)(size_t)));
int log_unlink __P((const char *, int, DB_ENV *)); 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_page_trickle; /* Pages written by memp_trickle. */
u_int32_t st_region_wait; /* Region lock granted after wait. */ 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_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. */ /* Mpool file statistics structure. */
@ -724,13 +779,13 @@ extern "C" {
#endif #endif
int memp_close __P((DB_MPOOL *)); int memp_close __P((DB_MPOOL *));
int memp_fclose __P((DB_MPOOLFILE *)); 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 memp_fopen __P((DB_MPOOL *, const char *,
int, int, int, size_t, int, DBT *, u_int8_t *, DB_MPOOLFILE **)); u_int32_t, int, size_t, DB_MPOOL_FINFO *, DB_MPOOLFILE **));
int memp_fput __P((DB_MPOOLFILE *, void *, int)); int memp_fput __P((DB_MPOOLFILE *, void *, u_int32_t));
int memp_fset __P((DB_MPOOLFILE *, void *, int)); int memp_fset __P((DB_MPOOLFILE *, void *, u_int32_t));
int memp_fsync __P((DB_MPOOLFILE *)); 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 memp_register __P((DB_MPOOL *, int,
int (*)(db_pgno_t, void *, DBT *), int (*)(db_pgno_t, void *, DBT *),
int (*)(db_pgno_t, void *, DBT *))); int (*)(db_pgno_t, void *, DBT *)));
@ -765,16 +820,21 @@ struct __db_txn_active {
}; };
struct __db_txn_stat { struct __db_txn_stat {
DB_LSN st_last_ckp; /* lsn of the last checkpoint */ DB_LSN st_last_ckp; /* lsn of the last checkpoint */
DB_LSN st_pending_ckp; /* last checkpoint did not finish */ DB_LSN st_pending_ckp; /* last checkpoint did not finish */
time_t st_time_ckp; /* time of last checkpoint */ time_t st_time_ckp; /* time of last checkpoint */
u_int32_t st_last_txnid; /* last transaction id given out */ 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_maxtxns; /* maximum number of active txns */
u_int32_t st_naborts; /* number of aborted transactions */ u_int32_t st_naborts; /* number of aborted transactions */
u_int32_t st_nbegins; /* number of begun transactions */ u_int32_t st_nbegins; /* number of begun transactions */
u_int32_t st_ncommits; /* number of committed transactions */ u_int32_t st_ncommits; /* number of committed transactions */
u_int32_t st_nactive; /* number of active transactions */ u_int32_t st_nactive; /* number of active transactions */
DB_TXN_ACTIVE *st_txnarray; /* array 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) #if defined(__cplusplus)
@ -782,11 +842,11 @@ extern "C" {
#endif #endif
int txn_abort __P((DB_TXN *)); int txn_abort __P((DB_TXN *));
int txn_begin __P((DB_TXNMGR *, DB_TXN *, 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_commit __P((DB_TXN *));
int txn_close __P((DB_TXNMGR *)); int txn_close __P((DB_TXNMGR *));
u_int32_t txn_id __P((DB_TXN *)); 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_prepare __P((DB_TXN *));
int txn_stat __P((DB_TXNMGR *, DB_TXN_STAT **, void *(*)(size_t))); int txn_stat __P((DB_TXNMGR *, DB_TXN_STAT **, void *(*)(size_t)));
int txn_unlink __P((const char *, int, DB_ENV *)); 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" #define DBM_SUFFIX ".db"
#if defined(_XPG4_2)
typedef struct {
char *dptr;
size_t dsize;
} datum;
#else
typedef struct { typedef struct {
char *dptr; char *dptr;
int dsize; int dsize;
} datum; } datum;
#endif
/* /*
* Translate DBM calls into DB calls so that DB doesn't step on the * Translate DBM calls into DB calls so that DB doesn't step on the
@ -894,7 +961,7 @@ typedef enum {
typedef struct entry { typedef struct entry {
char *key; char *key;
void *data; char *data;
} ENTRY; } ENTRY;
/* /*
@ -909,7 +976,7 @@ typedef struct entry {
#if defined(__cplusplus) #if defined(__cplusplus)
extern "C" { extern "C" {
#endif #endif
int __db_hcreate __P((unsigned int)); int __db_hcreate __P((size_t));
void __db_hdestroy __P((void)); void __db_hdestroy __P((void));
ENTRY *__db_hsearch __P((ENTRY, ACTION)); ENTRY *__db_hsearch __P((ENTRY, ACTION));
#if defined(__cplusplus) #if defined(__cplusplus)

View File

@ -1,7 +1,7 @@
/*- /*-
* See the file LICENSE for redistribution information. * See the file LICENSE for redistribution information.
* *
* Copyright (c) 1996, 1997 * Copyright (c) 1996, 1997, 1998
* Sleepycat Software. All rights reserved. * Sleepycat Software. All rights reserved.
*/ */
/* /*
@ -36,7 +36,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE. * 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_ #ifndef _DB_185_H_
@ -127,11 +127,11 @@ typedef struct __db {
/* Structure used to pass parameters to the btree routines. */ /* Structure used to pass parameters to the btree routines. */
typedef struct { typedef struct {
#define R_DUP 0x01 /* duplicate keys */ #define R_DUP 0x01 /* duplicate keys */
u_long flags; u_int32_t flags;
u_int cachesize; /* bytes to cache */ u_int32_t cachesize; /* bytes to cache */
int maxkeypage; /* maximum keys per page */ u_int32_t maxkeypage; /* maximum keys per page */
int minkeypage; /* minimum keys per page */ u_int32_t minkeypage; /* minimum keys per page */
u_int psize; /* page size */ u_int32_t psize; /* page size */
int (*compare) /* comparison function */ int (*compare) /* comparison function */
__P((const DBT *, const DBT *)); __P((const DBT *, const DBT *));
size_t (*prefix) /* prefix function */ size_t (*prefix) /* prefix function */
@ -144,10 +144,10 @@ typedef struct {
/* Structure used to pass parameters to the hashing routines. */ /* Structure used to pass parameters to the hashing routines. */
typedef struct { typedef struct {
u_int bsize; /* bucket size */ u_int32_t bsize; /* bucket size */
u_int ffactor; /* fill factor */ u_int32_t ffactor; /* fill factor */
u_int nelem; /* number of elements */ u_int32_t nelem; /* number of elements */
u_int cachesize; /* bytes to cache */ u_int32_t cachesize; /* bytes to cache */
u_int32_t /* hash function */ u_int32_t /* hash function */
(*hash) __P((const void *, size_t)); (*hash) __P((const void *, size_t));
int lorder; /* byte order */ int lorder; /* byte order */
@ -158,9 +158,9 @@ typedef struct {
#define R_FIXEDLEN 0x01 /* fixed-length records */ #define R_FIXEDLEN 0x01 /* fixed-length records */
#define R_NOKEY 0x02 /* key not required */ #define R_NOKEY 0x02 /* key not required */
#define R_SNAPSHOT 0x04 /* snapshot the input */ #define R_SNAPSHOT 0x04 /* snapshot the input */
u_long flags; u_int32_t flags;
u_int cachesize; /* bytes to cache */ u_int32_t cachesize; /* bytes to cache */
u_int psize; /* page size */ u_int32_t psize; /* page size */
int lorder; /* byte order */ int lorder; /* byte order */
size_t reclen; /* record length (fixed-length records) */ size_t reclen; /* record length (fixed-length records) */
u_char bval; /* delimiting byte (variable-length records */ u_char bval; /* delimiting byte (variable-length records */

View File

@ -1,10 +1,10 @@
/*- /*-
* See the file LICENSE for redistribution information. * See the file LICENSE for redistribution information.
* *
* Copyright (c) 1996, 1997 * Copyright (c) 1996, 1997, 1998
* Sleepycat Software. All rights reserved. * 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 #ifndef _DB_AM_H
#define _DB_AM_H #define _DB_AM_H

View File

@ -114,6 +114,9 @@ typedef struct _db_noop_args {
u_int32_t type; u_int32_t type;
DB_TXN *txnid; DB_TXN *txnid;
DB_LSN prev_lsn; DB_LSN prev_lsn;
u_int32_t fileid;
db_pgno_t pgno;
DB_LSN prevlsn;
} __db_noop_args; } __db_noop_args;
#endif #endif

View File

@ -1,10 +1,10 @@
/*- /*-
* See the file LICENSE for redistribution information. * See the file LICENSE for redistribution information.
* *
* Copyright (c) 1997 * Copyright (c) 1997, 1998
* Sleepycat Software. All rights reserved. * 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_ #ifndef _DB_CXX_H_
@ -178,11 +178,11 @@ class _exported DbLock
friend DbLockTab; friend DbLockTab;
public: public:
DbLock(unsigned int); DbLock(u_int);
DbLock(); DbLock();
unsigned int get_lock_id(); u_int get_lock_id();
void set_lock_id(unsigned int); void set_lock_id(u_int);
int put(DbLockTab *locktab); int put(DbLockTab *locktab);
@ -202,16 +202,16 @@ class _exported DbLockTab
friend DbEnv; friend DbEnv;
public: public:
int close(); int close();
int detect(int flags, int atype); int detect(u_int32_t flags, int atype);
int get(u_int32_t locker, int flags, const Dbt *obj, int get(u_int32_t locker, u_int32_t flags, const Dbt *obj,
db_lockmode_t lock_mode, DbLock *lock); db_lockmode_t lock_mode, DbLock *lock);
int id(u_int32_t *idp); 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); int nlist, DB_LOCKREQ **elistp);
// Create or remove new locktab files // 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); DbEnv* dbenv, DbLockTab **regionp);
static int unlink(const char *dir, int force, DbEnv* dbenv); static int unlink(const char *dir, int force, DbEnv* dbenv);
@ -252,13 +252,13 @@ class _exported DbLog
{ {
friend DbEnv; friend DbEnv;
public: 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(); int close();
static int compare(const DbLsn *lsn0, const DbLsn *lsn1); static int compare(const DbLsn *lsn0, const DbLsn *lsn1);
int file(DbLsn *lsn, char *namep, int len); int file(DbLsn *lsn, char *namep, int len);
int flush(const DbLsn *lsn); int flush(const DbLsn *lsn);
int get(DbLsn *lsn, Dbt *data, int flags); int get(DbLsn *lsn, Dbt *data, u_int32_t flags);
int put(DbLsn *lsn, const Dbt *data, int flags); int put(DbLsn *lsn, const Dbt *data, u_int32_t flags);
// Normally these would be called register and unregister to // Normally these would be called register and unregister to
// parallel the C interface, but "register" is a reserved word. // parallel the C interface, but "register" is a reserved word.
@ -268,7 +268,7 @@ public:
// Create or remove new log files // 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); DbEnv* dbenv, DbLog **regionp);
static int unlink(const char *dir, int force, DbEnv* dbenv); static int unlink(const char *dir, int force, DbEnv* dbenv);
@ -300,17 +300,17 @@ private:
class _exported DbMpoolFile class _exported DbMpoolFile
{ {
friend DbEnv;
public: public:
int close(); int close();
int get(db_pgno_t *pgnoaddr, int flags, void *pagep); int get(db_pgno_t *pgnoaddr, u_int32_t flags, void *pagep);
int put(void *pgaddr, int flags); int put(void *pgaddr, u_int32_t flags);
int set(void *pgaddr, int flags); int set(void *pgaddr, u_int32_t flags);
int sync(); int sync();
static int open(DbMpool *mp, const char *file, static int open(DbMpool *mp, const char *file,
int ftype, int flags, int mode, u_int32_t flags, int mode, size_t pagesize,
size_t pagesize, int lsn_offset, DB_MPOOL_FINFO *finfop, DbMpoolFile **mpf);
Dbt *pgcookie, u_int8_t *uid, DbMpoolFile **mpf);
private: private:
// We can add data to this class if needed // We can add data to this class if needed
@ -356,7 +356,7 @@ public:
// Create or remove new mpool files // 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); DbEnv* dbenv, DbMpool **regionp);
static int unlink(const char *dir, int force, DbEnv* dbenv); static int unlink(const char *dir, int force, DbEnv* dbenv);
@ -391,13 +391,13 @@ class _exported DbTxnMgr
friend DbEnv; friend DbEnv;
public: public:
int begin(DbTxn *pid, DbTxn **tid); 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 close();
int stat(DB_TXN_STAT **statp, void *(*db_malloc)(size_t)); int stat(DB_TXN_STAT **statp, void *(*db_malloc)(size_t));
// Create or remove new txnmgr files // 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); DbEnv* dbenv, DbTxnMgr **regionp);
static int unlink(const char *dir, int force, DbEnv* dbenv); static int unlink(const char *dir, int force, DbEnv* dbenv);
@ -510,12 +510,12 @@ public:
// Hash access method. // Hash access method.
// Fill factor. // Fill factor.
unsigned int get_h_ffactor() const; u_int32_t get_h_ffactor() const;
void set_h_ffactor(unsigned int); void set_h_ffactor(u_int32_t);
// Number of elements. // Number of elements.
unsigned int get_h_nelem() const; u_int32_t get_h_nelem() const;
void set_h_nelem(unsigned int); void set_h_nelem(u_int32_t);
// Hash function. // Hash function.
typedef u_int32_t (*h_hash_fcn)(const void *, u_int32_t); 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 // application with these arguments. Do not use it if you
// need to set other parameters via the access methods. // 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 // Use this constructor if you wish to *delay* the initialization
// of the db library. This is useful if you need to set // 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 // Used in conjunction with the default constructor to
// complete the initialization of the db library. // 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 automatically when DbEnv is destroyed, or can be
// called at any time to shut down Db. // called at any time to shut down Db.
@ -673,8 +673,8 @@ public:
void set_lk_modes(int); void set_lk_modes(int);
// Maximum number of locks. // Maximum number of locks.
unsigned int get_lk_max() const; u_int32_t get_lk_max() const;
void set_lk_max(unsigned int); void set_lk_max(u_int32_t);
// Deadlock detect on every conflict. // Deadlock detect on every conflict.
u_int32_t get_lk_detect() const; u_int32_t get_lk_detect() const;
@ -714,8 +714,8 @@ public:
DbTxnMgr *get_tx_info() const; DbTxnMgr *get_tx_info() const;
// Maximum number of transactions. // Maximum number of transactions.
unsigned int get_tx_max() const; u_int32_t get_tx_max() const;
void set_tx_max(unsigned int); void set_tx_max(u_int32_t);
// Dispatch function for recovery. // Dispatch function for recovery.
typedef int (*tx_recover_fcn)(DB_LOG *, DBT *, DB_LSN *, int, void *); typedef int (*tx_recover_fcn)(DB_LOG *, DBT *, DB_LSN *, int, void *);
@ -781,18 +781,18 @@ class _exported Db
friend DbEnv; friend DbEnv;
public: public:
int close(int flags); int close(u_int32_t flags);
int cursor(DbTxn *txnid, Dbc **cursorp); 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 fd(int *fdp);
int get(DbTxn *txnid, Dbt *key, Dbt *data, int flags); int get(DbTxn *txnid, Dbt *key, Dbt *data, u_int32_t flags);
int put(DbTxn *txnid, Dbt *key, Dbt *data, int flags); int put(DbTxn *txnid, Dbt *key, Dbt *data, u_int32_t flags);
int stat(void *sp, void *(*db_malloc)(size_t), int flags); int stat(void *sp, void *(*db_malloc)(size_t), u_int32_t flags);
int sync(int flags); int sync(u_int32_t flags);
DBTYPE get_type() const; 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); int mode, DbEnv *dbenv, DbInfo *info, Db **dbpp);
private: private:
@ -867,9 +867,9 @@ class _exported Dbc : protected DBC
public: public:
int close(); int close();
int del(int flags); int del(u_int32_t flags);
int get(Dbt* key, Dbt *data, int flags); int get(Dbt* key, Dbt *data, u_int32_t flags);
int put(Dbt* key, Dbt *data, int flags); int put(Dbt* key, Dbt *data, u_int32_t flags);
private: private:
// No data is permitted in this class (see comment at top) // No data is permitted in this class (see comment at top)

View File

@ -1,7 +1,7 @@
/*- /*-
* See the file LICENSE for redistribution information. * See the file LICENSE for redistribution information.
* *
* Copyright (c) 1996, 1997 * Copyright (c) 1996, 1997, 1998
* Sleepycat Software. All rights reserved. * Sleepycat Software. All rights reserved.
*/ */
/* /*
@ -36,26 +36,30 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE. * SUCH DAMAGE.
* *
* @(#)db_dispatch.h 10.1 (Sleepycat) 4/12/97 * @(#)db_dispatch.h 10.4 (Sleepycat) 5/3/98
*/ */
#ifndef _DB_DISPATCH_H #ifndef _DB_DISPATCH_H
#define _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 * Declarations and typedefs for the list of transaction IDs used during
* recovery. * recovery.
*/ */
struct __db_txnhead {
typedef struct __db_txnhead { LIST_HEAD(__db_headlink, __db_txnlist) head;
LIST_HEAD(__db_headlink, _db_txnlist) head;
u_int32_t maxid; u_int32_t maxid;
} __db_txnhead; int32_t generation;
};
typedef struct _db_txnlist { struct __db_txnlist {
LIST_ENTRY(_db_txnlist) links; LIST_ENTRY(__db_txnlist) links;
u_int32_t txnid; u_int32_t txnid;
} __db_txnlist; int32_t generation;
};
#define DB_log_BEGIN 0 #define DB_log_BEGIN 0
#define DB_txn_BEGIN 5 #define DB_txn_BEGIN 5

View File

@ -53,7 +53,8 @@ int __db_debug_print
__P((DB_LOG *, DBT *, DB_LSN *, int, void *)); __P((DB_LOG *, DBT *, DB_LSN *, int, void *));
int __db_debug_read __P((void *, __db_debug_args **)); int __db_debug_read __P((void *, __db_debug_args **));
int __db_noop_log 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 int __db_noop_print
__P((DB_LOG *, DBT *, DB_LSN *, int, void *)); __P((DB_LOG *, DBT *, DB_LSN *, int, void *));
int __db_noop_read __P((void *, __db_noop_args **)); 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_init __P((void *));
int __db_txnlist_add __P((void *, u_int32_t)); int __db_txnlist_add __P((void *, u_int32_t));
int __db_txnlist_find __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_end __P((void *));
void __db_txnlist_gen __P((void *, int));
void __db_txnlist_print __P((void *));
int __db_dput __P((DB *, int __db_dput __P((DB *,
DBT *, PAGE **, db_indx_t *, int (*)(DB *, u_int32_t, PAGE **))); DBT *, PAGE **, db_indx_t *, int (*)(DB *, u_int32_t, PAGE **)));
int __db_drem __P((DB *, 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 *)); u_int32_t, db_pgno_t, void **, u_int32_t *));
int __db_poff __P((DB *, const DBT *, db_pgno_t *, int __db_poff __P((DB *, const DBT *, db_pgno_t *,
int (*)(DB *, u_int32_t, PAGE **))); 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_doff __P((DB *, db_pgno_t, int (*)(DB *, PAGE *)));
int __db_moff __P((DB *, const DBT *, db_pgno_t)); int __db_moff __P((DB *, const DBT *, db_pgno_t));
void __db_loadme __P((void)); 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_prpage __P((PAGE *, int));
int __db_isbad __P((PAGE *, int)); int __db_isbad __P((PAGE *, int));
void __db_pr __P((u_int8_t *, u_int32_t)); 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 int __db_addrem_recover
__P((DB_LOG *, DBT *, DB_LSN *, int, void *)); __P((DB_LOG *, DBT *, DB_LSN *, int, void *));
int __db_split_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 int __db_addpage_recover
__P((DB_LOG *, DBT *, DB_LSN *, int, void *)); __P((DB_LOG *, DBT *, DB_LSN *, int, void *));
int __db_debug_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 int __db_noop_recover __P((DB_LOG *, DBT *, DB_LSN *, int, void *));
__P((DB_LOG *, DBT *, DB_LSN *, int, void *));
int __db_ret __P((DB *, int __db_ret __P((DB *,
PAGE *, u_int32_t, DBT *, void **, u_int32_t *)); PAGE *, u_int32_t, DBT *, void **, u_int32_t *));
int __db_retcopy __P((DBT *, int __db_retcopy __P((DBT *,

View File

@ -1,10 +1,10 @@
/*- /*-
* See the file LICENSE for redistribution information. * See the file LICENSE for redistribution information.
* *
* Copyright (c) 1996, 1997 * Copyright (c) 1996, 1997, 1998
* Sleepycat Software. All rights reserved. * 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_ #ifndef _DB_INTERNAL_H_
@ -12,8 +12,6 @@
#include "db.h" /* Standard DB include file. */ #include "db.h" /* Standard DB include file. */
#include "queue.h" #include "queue.h"
#include "os_func.h"
#include "os_ext.h"
/******************************************************* /*******************************************************
* General purpose constants and macros. * General purpose constants and macros.
@ -77,8 +75,8 @@
#define R_ADDR(base, offset) ((void *)((u_int8_t *)((base)->addr) + offset)) #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) #define R_OFFSET(base, p) ((u_int8_t *)(p) - (u_int8_t *)(base)->addr)
/* Free and free-string macros that overwrite memory during debugging. */ /* Free and free-string macros that overwrite memory. */
#ifdef DEBUG #ifdef DIAGNOSTIC
#undef FREE #undef FREE
#define FREE(p, len) { \ #define FREE(p, len) { \
memset(p, 0xff, len); \ memset(p, 0xff, len); \
@ -117,36 +115,41 @@ typedef struct __fn {
#undef DB_LINE #undef DB_LINE
#define 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!" */ /* Unused, or not-used-yet variable. "Shut that bloody compiler up!" */
#define COMPQUIET(n, v) (n) = (v) #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. * Files.
*******************************************************/ *******************************************************/
#ifndef MAXPATHLEN /* Maximum path length. */ /*
#ifdef PATH_MAX * We use 1024 as the maximum path length. It's too hard to figure out what
#define MAXPATHLEN PATH_MAX * the real path length is, as it was traditionally stored in <sys/param.h>,
#else * and that file isn't always available.
*/
#undef MAXPATHLEN
#define MAXPATHLEN 1024 #define MAXPATHLEN 1024
#endif
#endif
#define PATH_DOT "." /* Current working directory. */ #define PATH_DOT "." /* Current working directory. */
#define PATH_SEPARATOR "/" /* Path separator character. */ #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. * Mutex support.
*******************************************************/ *******************************************************/
@ -176,12 +179,12 @@ typedef struct __fn {
typedef struct _db_mutex_t { typedef struct _db_mutex_t {
#ifdef HAVE_SPINLOCKS #ifdef HAVE_SPINLOCKS
tsl_t tsl_resource; /* Resource test and set. */ tsl_t tsl_resource; /* Resource test and set. */
#ifdef DEBUG #ifdef DIAGNOSTIC
u_long pid; /* Lock holder: 0 or process pid. */ u_int32_t pid; /* Lock holder: 0 or process pid. */
#endif #endif
#else #else
u_int32_t off; /* Backing file offset. */ 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 #endif
u_int32_t spins; /* Spins before block. */ u_int32_t spins; /* Spins before block. */
u_int32_t mutex_set_wait; /* Granted after wait. */ u_int32_t mutex_set_wait; /* Granted after wait. */
@ -195,11 +198,11 @@ typedef struct _db_mutex_t {
*******************************************************/ *******************************************************/
/* Lock/unlock a DB thread. */ /* Lock/unlock a DB thread. */
#define DB_THREAD_LOCK(dbp) \ #define DB_THREAD_LOCK(dbp) \
(F_ISSET(dbp, DB_AM_THREAD) ? \ if (F_ISSET(dbp, DB_AM_THREAD)) \
__db_mutex_lock((db_mutex_t *)(dbp)->mutexp, -1) : 0) (void)__db_mutex_lock((db_mutex_t *)(dbp)->mutexp, -1);
#define DB_THREAD_UNLOCK(dbp) \ #define DB_THREAD_UNLOCK(dbp) \
(F_ISSET(dbp, DB_AM_THREAD) ? \ if (F_ISSET(dbp, DB_AM_THREAD)) \
__db_mutex_unlock((db_mutex_t *)(dbp)->mutexp, -1) : 0) (void)__db_mutex_unlock((db_mutex_t *)(dbp)->mutexp, -1);
/* Btree/recno local statistics structure. */ /* Btree/recno local statistics structure. */
struct __db_bt_lstat; typedef struct __db_bt_lstat DB_BTREE_LSTAT; struct __db_bt_lstat; typedef struct __db_bt_lstat DB_BTREE_LSTAT;
@ -228,7 +231,7 @@ typedef enum {
} APPNAME; } APPNAME;
/******************************************************* /*******************************************************
* Regions. * Shared memory regions.
*******************************************************/ *******************************************************/
/* /*
* The shared memory regions share an initial structure so that the general * The shared memory regions share an initial structure so that the general
@ -240,16 +243,69 @@ typedef enum {
*/ */
typedef struct _rlayout { typedef struct _rlayout {
db_mutex_t lock; /* Region mutex. */ db_mutex_t lock; /* Region mutex. */
#define DB_REGIONMAGIC 0x120897
u_int32_t valid; /* Valid magic number. */
u_int32_t refcnt; /* Region reference count. */ u_int32_t refcnt; /* Region reference count. */
size_t size; /* Region length. */ size_t size; /* Region length. */
int majver; /* Major version number. */ int majver; /* Major version number. */
int minver; /* Minor version number. */ int minver; /* Minor version number. */
int patch; /* Patch 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; u_int32_t flags;
} RLAYOUT; } 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. * Mpool.
*******************************************************/ *******************************************************/
@ -281,7 +337,7 @@ typedef struct __dbpginfo {
#define DB_LOGGING(dbp) \ #define DB_LOGGING(dbp) \
(F_ISSET(dbp, DB_AM_LOGGING) && !F_ISSET(dbp, DB_AM_RECOVER)) (F_ISSET(dbp, DB_AM_LOGGING) && !F_ISSET(dbp, DB_AM_RECOVER))
#ifdef DEBUG #ifdef DIAGNOSTIC
/* /*
* Debugging macro to log operations. * Debugging macro to log operations.
* If DEBUG_WOP is defined, log operations that modify the database. * If DEBUG_WOP is defined, log operations that modify the database.
@ -318,7 +374,7 @@ typedef struct __dbpginfo {
#else #else
#define DEBUG_LREAD(D, T, O, K, A, F) #define DEBUG_LREAD(D, T, O, K, A, F)
#define DEBUG_LWRITE(D, T, O, K, A, F) #define DEBUG_LWRITE(D, T, O, K, A, F)
#endif /* DEBUG */ #endif /* DIAGNOSTIC */
/******************************************************* /*******************************************************
* Transactions and recovery. * Transactions and recovery.
@ -339,4 +395,8 @@ struct __db_txn {
size_t off; /* Detail structure within region. */ size_t off; /* Detail structure within region. */
TAILQ_ENTRY(__db_txn) links; TAILQ_ENTRY(__db_txn) links;
}; };
#include "os_func.h"
#include "os_ext.h"
#endif /* !_DB_INTERNAL_H_ */ #endif /* !_DB_INTERNAL_H_ */

View File

@ -1,10 +1,10 @@
/*- /*-
* See the file LICENSE for redistribution information. * See the file LICENSE for redistribution information.
* *
* Copyright (c) 1996, 1997 * Copyright (c) 1996, 1997, 1998
* Sleepycat Software. All rights reserved. * 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_ #ifndef _DB_PAGE_H_
@ -29,6 +29,14 @@
#define PGNO_INVALID 0 /* Metadata page number, therefore illegal. */ #define PGNO_INVALID 0 /* Metadata page number, therefore illegal. */
#define PGNO_ROOT 1 /* Root is page #1. */ #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 BTREE METADATA PAGE LAYOUT
************************************************************************/ ************************************************************************/

View File

@ -1,10 +1,10 @@
/*- /*-
* See the file LICENSE for redistribution information. * See the file LICENSE for redistribution information.
* *
* Copyright (c) 1996, 1997 * Copyright (c) 1996, 1997, 1998
* Sleepycat Software. All rights reserved. * 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 */ /* Hash Headers */

View File

@ -1,7 +1,7 @@
/*- /*-
* See the file LICENSE for redistribution information. * See the file LICENSE for redistribution information.
* *
* Copyright (c) 1996, 1997 * Copyright (c) 1996, 1997, 1998
* Sleepycat Software. All rights reserved. * Sleepycat Software. All rights reserved.
*/ */
/* /*
@ -36,7 +36,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE. * SUCH DAMAGE.
* *
* @(#)db_swap.h 10.3 (Sleepycat) 6/10/97 * @(#)db_swap.h 10.5 (Sleepycat) 4/10/98
*/ */
#ifndef _DB_SWAP_H_ #ifndef _DB_SWAP_H_
@ -74,7 +74,7 @@
/* /*
* Little endian <==> big endian 16-bit swap macros. * Little endian <==> big endian 16-bit swap macros.
* M_16_SWAP swap a memory location * 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 * P_16_SWAP swap a referenced memory location
*/ */
#define M_16_SWAP(a) { \ #define M_16_SWAP(a) { \

View File

@ -1,7 +1,7 @@
/*- /*-
* See the file LICENSE for redistribution information. * See the file LICENSE for redistribution information.
* *
* Copyright (c) 1996, 1997 * Copyright (c) 1996, 1997, 1998
* Sleepycat Software. All rights reserved. * Sleepycat Software. All rights reserved.
*/ */
/* /*
@ -43,7 +43,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE. * SUCH DAMAGE.
* *
* @(#)hash.h 10.7 (Sleepycat) 11/1/97 * @(#)hash.h 10.8 (Sleepycat) 4/10/98
*/ */
/* Cursor structure definitions. */ /* Cursor structure definitions. */

View File

@ -2,7 +2,7 @@
#ifndef _hash_ext_h_ #ifndef _hash_ext_h_
#define _hash_ext_h_ #define _hash_ext_h_
int __ham_open __P((DB *, DB_INFO *)); 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_c_iclose __P((DB *, DBC *));
int __ham_expand_table __P((HTAB *)); int __ham_expand_table __P((HTAB *));
u_int32_t __ham_call_hash __P((HTAB *, u_int8_t *, int32_t)); u_int32_t __ham_call_hash __P((HTAB *, u_int8_t *, int32_t));
@ -75,7 +75,7 @@ int __ham_mswap __P((void *));
#ifdef DEBUG #ifdef DEBUG
void __ham_dump_bucket __P((HTAB *, u_int32_t)); void __ham_dump_bucket __P((HTAB *, u_int32_t));
#endif #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)); 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_func2 __P((const void *, u_int32_t));
u_int32_t __ham_func3 __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_prev __P((HTAB *, HASH_CURSOR *, db_lockmode_t));
int __ham_item_next __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_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_del_pair __P((HTAB *, HASH_CURSOR *, int));
int __ham_replpair __P((HTAB *, HASH_CURSOR *, DBT *, u_int32_t)); int __ham_replpair __P((HTAB *, HASH_CURSOR *, DBT *, u_int32_t));
void __ham_onpage_replace __P((PAGE *, size_t, u_int32_t, int32_t, void __ham_onpage_replace __P((PAGE *, size_t, u_int32_t, int32_t,
int32_t, DBT *)); int32_t, DBT *));
int __ham_split_page __P((HTAB *, u_int32_t, u_int32_t)); 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 __ham_add_el
int)); __P((HTAB *, HASH_CURSOR *, const DBT *, const DBT *, int));
void __ham_copy_item __P((HTAB *, PAGE *, int, PAGE *)); void __ham_copy_item __P((HTAB *, PAGE *, u_int32_t, PAGE *));
int __ham_add_ovflpage __P((HTAB *, PAGE *, int, 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_new_page __P((HTAB *, u_int32_t, u_int32_t, PAGE **));
int __ham_del_page __P((DB *, 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_get_page __P((DB *, db_pgno_t, PAGE **));
int __ham_overflow_page __P((DB *, u_int32_t, PAGE **)); int __ham_overflow_page __P((DB *, u_int32_t, PAGE **));
#ifdef DEBUG #ifdef DEBUG
int __bucket_to_page __P((HTAB *, int)); db_pgno_t __bucket_to_page __P((HTAB *, db_pgno_t));
#endif #endif
void __ham_init_ovflpages __P((HTAB *)); void __ham_init_ovflpages __P((HTAB *));
int __ham_get_cpage __P((HTAB *, HASH_CURSOR *, db_lockmode_t)); int __ham_get_cpage __P((HTAB *, HASH_CURSOR *, db_lockmode_t));
int __ham_next_cpage __P((HTAB *, HASH_CURSOR *, db_pgno_t, int __ham_next_cpage
int, int)); __P((HTAB *, HASH_CURSOR *, db_pgno_t, int, u_int32_t));
void __ham_dpair __P((DB *, PAGE *, u_int32_t)); void __ham_dpair __P((DB *, PAGE *, u_int32_t));
int __ham_insdel_recover int __ham_insdel_recover
__P((DB_LOG *, DBT *, DB_LSN *, int, void *)); __P((DB_LOG *, DBT *, DB_LSN *, int, void *));

View File

@ -1,16 +1,19 @@
/*- /*-
* See the file LICENSE for redistribution information. * See the file LICENSE for redistribution information.
* *
* Copyright (c) 1996, 1997 * Copyright (c) 1996, 1997, 1998
* Sleepycat Software. All rights reserved. * 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; typedef struct __db_lockobj DB_LOCKOBJ;
#define DB_DEFAULT_LOCK_FILE "__db_lock.share" #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 * 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. */ /* Macros to lock/unlock the region. */
#define LOCK_LOCKREGION(lt) \ #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) \ #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 * 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)) #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 { struct __db_lockobj {
SH_DBT lockobj; /* Identifies object locked. */ SH_DBT lockobj; /* Identifies object locked. */
SH_TAILQ_ENTRY links; /* Links for free list. */ SH_TAILQ_ENTRY links; /* Links for free list. */
@ -98,12 +98,14 @@ struct __db_lockobj {
#define holders dlinks._holders #define holders dlinks._holders
#define heldby dlinks._heldby #define heldby dlinks._heldby
/*
* The lock table is the per-process cookie returned from a lock_open call.
*/
struct __db_locktab { struct __db_locktab {
DB_ENV *dbenv; /* Environment. */ DB_ENV *dbenv; /* Environment. */
int fd; /* mapped file descriptor */ REGINFO reginfo; /* Region information. */
DB_LOCKREGION *region; /* address of shared memory region */ DB_LOCKREGION *region; /* Address of shared memory region. */
DB_HASHTAB *hashtab; /* Beginning of hash table. */ DB_HASHTAB *hashtab; /* Beginning of hash table. */
size_t reg_size; /* last known size of lock region */
void *mem; /* Beginning of string space. */ void *mem; /* Beginning of string space. */
u_int8_t *conflicts; /* Pointer to conflict matrix. */ u_int8_t *conflicts; /* Pointer to conflict matrix. */
}; };
@ -112,21 +114,6 @@ struct __db_locktab {
#define CONFLICTS(T, HELD, WANTED) \ #define CONFLICTS(T, HELD, WANTED) \
T->conflicts[HELD * T->region->nmodes + WANTED] 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 * Resources in the lock region. Used to indicate which resource
* is running low when we need to grow the region. * 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((N) * sizeof(DB_LOCKOBJ), sizeof(size_t)) + \
ALIGN(STRING_SIZE(N), 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" #include "lock_ext.h"

View File

@ -1,14 +1,17 @@
/* DO NOT EDIT: automatically built by dist/distrib. */ /* DO NOT EDIT: automatically built by dist/distrib. */
#ifndef _lock_ext_h_ #ifndef _lock_ext_h_
#define _lock_ext_h_ #define _lock_ext_h_
void __lock_dump_region __P((DB_LOCKTAB *, u_int));
int __lock_is_locked int __lock_is_locked
__P((DB_LOCKTAB *, u_int32_t, DBT *, db_lockmode_t)); __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 *, int __lock_getobj __P((DB_LOCKTAB *,
u_int32_t, const DBT *, u_int32_t type, DB_LOCKOBJ **)); 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_cmp __P((const DBT *, DB_LOCKOBJ *));
int __lock_locker_cmp __P((u_int32_t, DB_LOCKOBJ *)); int __lock_locker_cmp __P((u_int32_t, DB_LOCKOBJ *));
int __lock_ohash __P((const DBT *)); u_int32_t __lock_ohash __P((const DBT *));
u_int32_t __lock_locker_hash __P((u_int32_t));
u_int32_t __lock_lhash __P((DB_LOCKOBJ *)); u_int32_t __lock_lhash __P((DB_LOCKOBJ *));
u_int32_t __lock_locker_hash __P((u_int32_t));
#endif /* _lock_ext_h_ */ #endif /* _lock_ext_h_ */

View File

@ -1,10 +1,10 @@
/*- /*-
* See the file LICENSE for redistribution information. * See the file LICENSE for redistribution information.
* *
* Copyright (c) 1996, 1997 * Copyright (c) 1996, 1997, 1998
* Sleepycat Software. All rights reserved. * Sleepycat Software. All rights reserved.
* *
* @(#)log.h 10.19 (Sleepycat) 1/17/98 * @(#)log.h 10.25 (Sleepycat) 4/10/98
*/ */
#ifndef _LOG_H_ #ifndef _LOG_H_
@ -15,9 +15,10 @@ struct __hdr; typedef struct __hdr HDR;
struct __log; typedef struct __log LOG; struct __log; typedef struct __log LOG;
struct __log_persist; typedef struct __log_persist LOGP; struct __log_persist; typedef struct __log_persist LOGP;
#ifndef MAXLFNAME
#define MAXLFNAME 99999 /* Maximum log file name. */ #define MAXLFNAME 99999 /* Maximum log file name. */
#define LFNAME "log.%05d" /* Log file name template. */ #define LFNAME "log.%05d" /* Log file name template. */
#endif
/* Default log name. */ /* Default log name. */
#define DB_DEFAULT_LOG_FILE "__db_log.share" #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)) \ if (F_ISSET(dblp, DB_AM_THREAD)) \
(void)__db_mutex_unlock((dblp)->mutexp, -1); (void)__db_mutex_unlock((dblp)->mutexp, -1);
#define LOCK_LOGREGION(dblp) \ #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) \ #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. * The per-process table that maps log file-id's to DB structures.
*/ */
typedef struct __db_entry { typedef struct __db_entry {
DB *dbp; /* Associated DB structure. */ DB *dbp; /* Associated DB structure. */
int refcount; /* Reference counted. */ u_int32_t refcount; /* Reference counted. */
int deleted; /* File was not found during open. */ int deleted; /* File was not found during open. */
} DB_ENTRY; } DB_ENTRY;
/* /*
@ -75,10 +78,9 @@ struct __db_log {
LOG *lp; /* Address of the shared LOG. */ LOG *lp; /* Address of the shared LOG. */
DB_ENV *dbenv; /* Reference to error information. */ DB_ENV *dbenv; /* Reference to error information. */
REGINFO reginfo; /* Region information. */
void *maddr; /* Address of mmap'd region. */
void *addr; /* Address of shalloc() region. */ void *addr; /* Address of shalloc() region. */
int fd; /* Region file descriptor. */
char *dir; /* Directory argument. */ char *dir; /* Directory argument. */
@ -131,7 +133,7 @@ struct __log {
u_int32_t w_off; /* Current write offset in the file. */ 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. */ time_t chkpt; /* Time of the last checkpoint. */
DB_LOG_STAT stat; /* Log statistics. */ DB_LOG_STAT stat; /* Log statistics. */
@ -159,9 +161,8 @@ struct __fname {
u_int32_t id; /* Logging file id. */ u_int32_t id; /* Logging file id. */
DBTYPE s_type; /* Saved DB type. */ DBTYPE s_type; /* Saved DB type. */
u_int32_t fileid_off; /* Unique file id offset. */
size_t name_off; /* Name 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. */ /* File open/close register log record opcodes. */

View File

@ -13,8 +13,8 @@ int __log_register_read __P((void *, __log_register_args **));
int __log_init_print __P((DB_ENV *)); int __log_init_print __P((DB_ENV *));
int __log_init_recover __P((DB_ENV *)); int __log_init_recover __P((DB_ENV *));
int __log_findckp __P((DB_LOG *, DB_LSN *)); int __log_findckp __P((DB_LOG *, DB_LSN *));
int __log_get __P((DB_LOG *, DB_LSN *, DBT *, int, int)); int __log_get __P((DB_LOG *, DB_LSN *, DBT *, u_int32_t, int));
int __log_put __P((DB_LOG *, DB_LSN *, const DBT *, int)); int __log_put __P((DB_LOG *, DB_LSN *, const DBT *, u_int32_t));
int __log_name __P((DB_LOG *, int, char **)); int __log_name __P((DB_LOG *, int, char **));
int __log_register_recover int __log_register_recover
__P((DB_LOG *, DBT *, DB_LSN *, int, void *)); __P((DB_LOG *, DBT *, DB_LSN *, int, void *));

View File

@ -1,10 +1,10 @@
/*- /*-
* See the file LICENSE for redistribution information. * See the file LICENSE for redistribution information.
* *
* Copyright (c) 1996, 1997 * Copyright (c) 1996, 1997, 1998
* Sleepycat Software. All rights reserved. * 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; struct __bh; typedef struct __bh BH;
@ -16,10 +16,12 @@ struct __mpoolfile; typedef struct __mpoolfile MPOOLFILE;
#define DB_DEFAULT_MPOOL_FILE "__db_mpool.share" #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. * require a minimum of 20K.
*/ */
#ifndef DB_CACHESIZE_DEF
#define DB_CACHESIZE_DEF (128 * 1024) #define DB_CACHESIZE_DEF (128 * 1024)
#endif
#define DB_CACHESIZE_MIN ( 20 * 1024) #define DB_CACHESIZE_MIN ( 20 * 1024)
#define INVALID 0 /* Invalid shared memory offset. */ #define INVALID 0 /* Invalid shared memory offset. */
@ -79,30 +81,30 @@ struct __mpoolfile; typedef struct __mpoolfile MPOOLFILE;
#define LOCKINIT(dbmp, mutexp) \ #define LOCKINIT(dbmp, mutexp) \
if (F_ISSET(dbmp, MP_LOCKHANDLE | MP_LOCKREGION)) \ if (F_ISSET(dbmp, MP_LOCKHANDLE | MP_LOCKREGION)) \
(void)__db_mutex_init(mutexp, \ (void)__db_mutex_init(mutexp, \
MUTEX_LOCK_OFFSET((dbmp)->maddr, mutexp)) MUTEX_LOCK_OFFSET((dbmp)->reginfo.addr, mutexp))
#define LOCKHANDLE(dbmp, mutexp) \ #define LOCKHANDLE(dbmp, mutexp) \
if (F_ISSET(dbmp, MP_LOCKHANDLE)) \ 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) \ #define UNLOCKHANDLE(dbmp, mutexp) \
if (F_ISSET(dbmp, MP_LOCKHANDLE)) \ if (F_ISSET(dbmp, MP_LOCKHANDLE)) \
(void)__db_mutex_unlock(mutexp, (dbmp)->fd) (void)__db_mutex_unlock(mutexp, (dbmp)->reginfo.fd)
#define LOCKREGION(dbmp) \ #define LOCKREGION(dbmp) \
if (F_ISSET(dbmp, MP_LOCKREGION)) \ if (F_ISSET(dbmp, MP_LOCKREGION)) \
(void)__db_mutex_lock(&((RLAYOUT *)(dbmp)->mp)->lock, \ (void)__db_mutex_lock(&((RLAYOUT *)(dbmp)->mp)->lock, \
(dbmp)->fd) (dbmp)->reginfo.fd)
#define UNLOCKREGION(dbmp) \ #define UNLOCKREGION(dbmp) \
if (F_ISSET(dbmp, MP_LOCKREGION)) \ if (F_ISSET(dbmp, MP_LOCKREGION)) \
(void)__db_mutex_unlock(&((RLAYOUT *)(dbmp)->mp)->lock, \ (void)__db_mutex_unlock(&((RLAYOUT *)(dbmp)->mp)->lock, \
(dbmp)->fd) (dbmp)->reginfo.fd)
#define LOCKBUFFER(dbmp, bhp) \ #define LOCKBUFFER(dbmp, bhp) \
if (F_ISSET(dbmp, MP_LOCKREGION)) \ 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) \ #define UNLOCKBUFFER(dbmp, bhp) \
if (F_ISSET(dbmp, MP_LOCKREGION)) \ 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 -- * DB_MPOOL --
@ -120,20 +122,16 @@ struct __db_mpool {
/* These fields are not protected. */ /* These fields are not protected. */
DB_ENV *dbenv; /* Reference to error information. */ DB_ENV *dbenv; /* Reference to error information. */
REGINFO reginfo; /* Region information. */
MPOOL *mp; /* Address of the shared MPOOL. */ MPOOL *mp; /* Address of the shared MPOOL. */
void *maddr; /* Address of mmap'd region. */
void *addr; /* Address of shalloc() region. */ void *addr; /* Address of shalloc() region. */
DB_HASHTAB *htab; /* Hash table of bucket headers. */ DB_HASHTAB *htab; /* Hash table of bucket headers. */
int fd; /* Underlying mmap'd fd. */ #define MP_LOCKHANDLE 0x01 /* Threaded, lock handles and region. */
#define MP_LOCKREGION 0x02 /* Concurrent access, lock region. */
#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. */
u_int32_t flags; u_int32_t flags;
}; };
@ -146,8 +144,8 @@ struct __db_mpreg {
int ftype; /* File type. */ int ftype; /* File type. */
/* Pgin, pgout routines. */ /* Pgin, pgout routines. */
int (*pgin) __P((db_pgno_t, void *, DBT *)); int (DB_CALLBACK *pgin) __P((db_pgno_t, void *, DBT *));
int (*pgout) __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. */ size_t htab_buckets; /* Number of hash table entries. */
DB_LSN lsn; /* Maximum checkpoint LSN. */ 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. */ DB_MPOOL_STAT stat; /* Global mpool statistics. */
@ -225,7 +223,9 @@ struct __mpoolfile {
u_int32_t ref; /* Reference count. */ u_int32_t ref; /* Reference count. */
int ftype; /* File type. */ 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 path_off; /* File name location. */
size_t fileid_off; /* File identification 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_len; /* Pgin/pgout cookie length. */
size_t pgcookie_off; /* Pgin/pgout cookie location. */ 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 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_CAN_MMAP 0x01 /* If the file can be mmap'd. */
#define MP_TEMP 0x02 /* Backing file is a temporary. */ #define MP_TEMP 0x02 /* Backing file is a temporary. */

View File

@ -7,13 +7,13 @@ int __memp_pgread __P((DB_MPOOLFILE *, BH *, int));
int __memp_pgwrite __P((DB_MPOOLFILE *, BH *, int *, int *)); int __memp_pgwrite __P((DB_MPOOLFILE *, BH *, int *, int *));
int __memp_pg __P((DB_MPOOLFILE *, BH *, int)); int __memp_pg __P((DB_MPOOLFILE *, BH *, int));
void __memp_bhfree __P((DB_MPOOL *, MPOOLFILE *, BH *, int)); void __memp_bhfree __P((DB_MPOOL *, MPOOLFILE *, BH *, int));
int __memp_fopen __P((DB_MPOOL *, MPOOLFILE *, const char *, int, int __memp_fopen __P((DB_MPOOL *, MPOOLFILE *, const char *,
int, int, size_t, int, DBT *, u_int8_t *, int, DB_MPOOLFILE **)); u_int32_t, int, size_t, int, DB_MPOOL_FINFO *, DB_MPOOLFILE **));
char * __memp_fn __P((DB_MPOOLFILE *)); char * __memp_fn __P((DB_MPOOLFILE *));
char * __memp_fns __P((DB_MPOOL *, 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_ralloc __P((DB_MPOOL *, size_t, size_t *, void *));
int __memp_ropen int __memp_ropen
__P((DB_MPOOL *, const char *, size_t, int, int)); __P((DB_MPOOL *, const char *, size_t, int, int, u_int32_t));
int __memp_rclose __P((DB_MPOOL *)); int __mp_xxx_fd __P((DB_MPOOLFILE *, int *));
#endif /* _mp_ext_h_ */ #endif /* _mp_ext_h_ */

View File

@ -1,7 +1,7 @@
/* DO NOT EDIT: automatically built by dist/distrib. */ /* DO NOT EDIT: automatically built by dist/distrib. */
#ifndef _mutex_ext_h_ #ifndef _mutex_ext_h_
#define _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_lock __P((db_mutex_t *, int));
int __db_mutex_unlock __P((db_mutex_t *, int)); int __db_mutex_unlock __P((db_mutex_t *, int));
#endif /* _mutex_ext_h_ */ #endif /* _mutex_ext_h_ */

View File

@ -2,23 +2,29 @@
#ifndef _os_ext_h_ #ifndef _os_ext_h_
#define _os_ext_h_ #define _os_ext_h_
int __db_abspath __P((const char *)); int __db_abspath __P((const char *));
char *__db_strdup __P((const char *));
void *__db_calloc __P((size_t, size_t)); void *__db_calloc __P((size_t, size_t));
void *__db_malloc __P((size_t)); void *__db_malloc __P((size_t));
void *__db_realloc __P((void *, size_t)); void *__db_realloc __P((void *, size_t));
int __os_oldwin __P((void));
int __os_dirlist __P((const char *, char ***, int *)); int __os_dirlist __P((const char *, char ***, int *));
void __os_dirfree __P((char **, int)); void __os_dirfree __P((char **, int));
int __db_fileid __P((DB_ENV *, const char *, int, u_int8_t *)); int __db_fileid __P((DB_ENV *, const char *, int, u_int8_t *));
int __db_fsync __P((int)); int __db_fsync __P((int));
int __os_map __P((int, size_t, int, int, void **)); int __db_mapanon_ok __P((int));
int __os_unmap __P((void *, size_t)); int __db_mapinit __P((void));
int __db_oflags __P((int)); int __db_mapregion __P((char *, REGINFO *));
int __db_open __P((const char *, int, int, int, int *)); 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)); int __db_close __P((int));
char *__db_rpath __P((const char *)); char *__db_rpath __P((const char *));
int __db_read __P((int, void *, size_t, ssize_t *)); int __db_read __P((int, void *, size_t, ssize_t *));
int __db_write __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_sleep __P((u_long, u_long));
int __os_spin __P((void)); int __os_spin __P((void));
int __os_exists __P((const char *, int *)); int __os_exists __P((const char *, int *));

View File

@ -1,40 +1,40 @@
/*- /*-
* See the file LICENSE for redistribution information. * See the file LICENSE for redistribution information.
* *
* Copyright (c) 1997 * Copyright (c) 1997, 1998
* Sleepycat Software. All rights reserved. * 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. */ /* Calls which can be replaced by the application. */
struct __db_jumptab { struct __db_jumptab {
int (*db_close) __P((int)); /* DB_FUNC_CLOSE */ int (*j_close) __P((int)); /* DB_FUNC_CLOSE */
void (*db_dirfree) __P((char **, int)); /* DB_FUNC_DIRFREE */ void (*j_dirfree) __P((char **, int)); /* DB_FUNC_DIRFREE */
int (*db_dirlist) /* DB_FUNC_DIRLIST */ int (*j_dirlist) /* DB_FUNC_DIRLIST */
__P((const char *, char ***, int *)); __P((const char *, char ***, int *));
int (*db_exists) /* DB_FUNC_EXISTS */ int (*j_exists) /* DB_FUNC_EXISTS */
__P((const char *, int *)); __P((const char *, int *));
void (*db_free) __P((void *)); /* DB_FUNC_FREE */ void (*j_free) __P((void *)); /* DB_FUNC_FREE */
int (*db_fsync) __P((int)); /* DB_FUNC_FSYNC */ int (*j_fsync) __P((int)); /* DB_FUNC_FSYNC */
int (*db_ioinfo) __P((const char *, /* DB_FUNC_IOINFO */ int (*j_ioinfo) __P((const char *, /* DB_FUNC_IOINFO */
int, u_int32_t *, u_int32_t *, u_int32_t *)); int, u_int32_t *, u_int32_t *, u_int32_t *));
void *(*db_malloc) __P((size_t)); /* DB_FUNC_MALLOC */ void *(*j_malloc) __P((size_t)); /* DB_FUNC_MALLOC */
int (*db_map) /* DB_FUNC_MAP */ int (*j_map) /* DB_FUNC_MAP */
__P((int, size_t, int, int, void **)); __P((char *, int, size_t, int, int, int, void **));
int (*db_open) /* DB_FUNC_OPEN */ int (*j_open) /* DB_FUNC_OPEN */
__P((const char *, int, ...)); __P((const char *, int, ...));
ssize_t (*db_read) __P((int, void *, size_t)); /* DB_FUNC_READ */ ssize_t (*j_read) __P((int, void *, size_t)); /* DB_FUNC_READ */
void *(*db_realloc) __P((void *, size_t)); /* DB_FUNC_REALLOC */ void *(*j_realloc) __P((void *, size_t)); /* DB_FUNC_REALLOC */
int (*db_seek) /* DB_FUNC_SEEK */ int (*j_runlink) __P((char *)); /* DB_FUNC_RUNLINK */
__P((int, size_t, db_pgno_t, u_long, int)); int (*j_seek) /* DB_FUNC_SEEK */
int (*db_sleep) __P((u_long, u_long)); /* DB_FUNC_SLEEP */ __P((int, size_t, db_pgno_t, u_int32_t, int, int));
char *(*db_strdup) __P((const char *)); /* DB_FUNC_STRDUP */ int (*j_sleep) __P((u_long, u_long)); /* DB_FUNC_SLEEP */
int (*db_unlink) __P((const char *)); /* DB_FUNC_UNLINK */ int (*j_unlink) __P((const char *)); /* DB_FUNC_UNLINK */
int (*db_unmap) __P((void *, size_t)); /* DB_FUNC_UNMAP */ int (*j_unmap) __P((void *, size_t)); /* DB_FUNC_UNMAP */
ssize_t (*db_write) /* DB_FUNC_WRITE */ ssize_t (*j_write) /* DB_FUNC_WRITE */
__P((int, const void *, size_t)); __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; 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. * Names used by DB to call through the jump table.
* *
* The naming scheme goes like this: if the functionality the application can * 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 * 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 * 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 * 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 * 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. * parts of DB should be calling __db_XXX functions.
*/ */
#define __os_close __db_jump.db_close /* __db_close is a wrapper. */ #define __os_close __db_jump.j_close /* __db_close is a wrapper. */
#define __db_dirfree __db_jump.db_dirfree #define __db_dirfree __db_jump.j_dirfree
#define __db_dirlist __db_jump.db_dirlist #define __db_dirlist __db_jump.j_dirlist
#define __db_exists __db_jump.db_exists #define __db_exists __db_jump.j_exists
#define __db_free __db_jump.db_free #define __db_free __db_jump.j_free
#define __os_fsync __db_jump.db_fsync /* __db_fsync is a wrapper. */ #define __os_fsync __db_jump.j_fsync /* __db_fsync is a wrapper. */
#define __db_ioinfo __db_jump.db_ioinfo #define __db_ioinfo __db_jump.j_ioinfo
#define __db_map __db_jump.db_map #define __os_open __db_jump.j_open /* __db_open is a wrapper. */
#define __os_open __db_jump.db_open /* __db_open is a wrapper. */ #define __os_read __db_jump.j_read /* __db_read is a wrapper. */
#define __os_read __db_jump.db_read /* __db_read is a wrapper. */ #define __db_seek __db_jump.j_seek
#define __db_seek __db_jump.db_seek #define __db_sleep __db_jump.j_sleep
#define __db_sleep __db_jump.db_sleep #define __os_unlink __db_jump.j_unlink /* __db_unlink is a wrapper. */
#define __db_strdup __db_jump.db_strdup #define __os_write __db_jump.j_write /* __db_write is a wrapper. */
#define __os_unlink __db_jump.db_unlink /* __db_unlink is a wrapper. */ #define __db_yield __db_jump.j_yield
#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

View File

@ -1,6 +1,6 @@
/* BSDI $Id$ */ /* BSDI $Id$ */
/* /*
* Copyright (c) 1991, 1993 * Copyright (c) 1991, 1993
* The Regents of the University of California. All rights reserved. * The Regents of the University of California. All rights reserved.
* *

View File

@ -1,10 +1,10 @@
/*- /*-
* See the file LICENSE for redistribution information. * See the file LICENSE for redistribution information.
* *
* Copyright (c) 1996, 1997 * Copyright (c) 1996, 1997, 1998
* Sleepycat Software. All rights reserved. * 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_ #ifndef _SYS_SHQUEUE_H_
#define _SYS_SHQUEUE_H_ #define _SYS_SHQUEUE_H_

View File

@ -1,10 +1,10 @@
/*- /*-
* See the file LICENSE for redistribution information. * See the file LICENSE for redistribution information.
* *
* Copyright (c) 1996, 1997 * Copyright (c) 1996, 1997, 1998
* Sleepycat Software. All rights reserved. * Sleepycat Software. All rights reserved.
* *
* @(#)txn.h 10.11 (Sleepycat) 10/25/97 * @(#)txn.h 10.15 (Sleepycat) 4/21/98
*/ */
#ifndef _TXN_H_ #ifndef _TXN_H_
#define _TXN_H_ #define _TXN_H_
@ -52,12 +52,11 @@ struct __db_txnmgr {
TAILQ_HEAD(_chain, __db_txn) txn_chain; TAILQ_HEAD(_chain, __db_txn) txn_chain;
/* These fields are not protected. */ /* These fields are not protected. */
REGINFO reginfo; /* Region information. */
DB_ENV *dbenv; /* Environment. */ DB_ENV *dbenv; /* Environment. */
int (*recover) /* Recovery dispatch routine */ int (*recover) /* Recovery dispatch routine */
__P((DB_LOG *, DBT *, DB_LSN *, int, void *)); __P((DB_LOG *, DBT *, DB_LSN *, int, void *));
int fd; /* mapped file descriptor */ u_int32_t flags; /* DB_TXN_NOSYNC, DB_THREAD */
u_int flags; /* DB_TXN_NOSYNC, DB_THREAD */
size_t reg_size; /* how large we think the region is */
DB_TXNREGION *region; /* address of shared memory region */ DB_TXNREGION *region; /* address of shared memory region */
void *mem; /* address of the shalloc space */ void *mem; /* address of the shalloc space */
}; };
@ -102,17 +101,16 @@ struct __db_txnregion {
(void)__db_mutex_unlock((tmgrp)->mutexp, -1) (void)__db_mutex_unlock((tmgrp)->mutexp, -1)
#define LOCK_TXNREGION(tmgrp) \ #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) \ #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. * Log record types.
*/ */
#define TXN_BEGIN 1 #define TXN_COMMIT 1
#define TXN_COMMIT 2 #define TXN_PREPARE 2
#define TXN_PREPARE 3 #define TXN_CHECKPOINT 3
#define TXN_CHECKPOINT 4
#include "txn_auto.h" #include "txn_auto.h"
#include "txn_ext.h" #include "txn_ext.h"

View File

@ -1,28 +1,21 @@
/*- /*-
* See the file LICENSE for redistribution information. * See the file LICENSE for redistribution information.
* *
* Copyright (c) 1996, 1997 * Copyright (c) 1996, 1997, 1998
* Sleepycat Software. All rights reserved. * Sleepycat Software. All rights reserved.
*/ */
#include "config.h" #include "config.h"
#ifndef lint #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 */ #endif /* not lint */
#ifndef NO_SYSTEM_INCLUDES #ifndef NO_SYSTEM_INCLUDES
#include <sys/types.h> #include <sys/types.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <errno.h> #include <errno.h>
#include <fcntl.h>
#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h> #include <string.h>
#include <unistd.h>
#endif #endif
#include "db_int.h" #include "db_int.h"
@ -34,248 +27,15 @@ static const char sccsid[] = "@(#)lock.c 10.43 (Sleepycat) 1/8/98";
#include "db_am.h" #include "db_am.h"
static void __lock_checklocker __P((DB_LOCKTAB *, struct __db_lock *, int)); 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 void __lock_freeobj __P((DB_LOCKTAB *, DB_LOCKOBJ *));
static int __lock_get_internal __P((DB_LOCKTAB *, u_int32_t, int, const DBT *, static int __lock_get_internal __P((DB_LOCKTAB *, u_int32_t, u_int32_t,
db_lockmode_t, struct __db_lock **)); const DBT *, db_lockmode_t, struct __db_lock **));
static int __lock_grow_region __P((DB_LOCKTAB *, int, size_t));
static int __lock_put_internal __P((DB_LOCKTAB *, struct __db_lock *, int)); static int __lock_put_internal __P((DB_LOCKTAB *, struct __db_lock *, int));
static void __lock_remove_waiter static void __lock_remove_waiter
__P((DB_LOCKTAB *, DB_LOCKOBJ *, struct __db_lock *, db_status_t)); __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 int
lock_open(path, flags, mode, dbenv, ltp) lock_id(lt, idp)
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)
DB_LOCKTAB *lt; DB_LOCKTAB *lt;
u_int32_t *idp; u_int32_t *idp;
{ {
@ -294,8 +54,8 @@ lock_id (lt, idp)
int int
lock_vec(lt, locker, flags, list, nlist, elistp) lock_vec(lt, locker, flags, list, nlist, elistp)
DB_LOCKTAB *lt; DB_LOCKTAB *lt;
u_int32_t locker; u_int32_t locker, flags;
int flags, nlist; int nlist;
DB_LOCKREQ *list, **elistp; DB_LOCKREQ *list, **elistp;
{ {
struct __db_lock *lp; 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); for (lp = SH_LIST_FIRST(&sh_locker->heldby, __db_lock);
lp != NULL; lp != NULL;
lp = SH_LIST_FIRST(&sh_locker->heldby, __db_lock)) { 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; break;
} }
__lock_freeobj(lt, sh_locker); __lock_freeobj(lt, sh_locker);
@ -436,8 +196,7 @@ lock_vec(lt, locker, flags, list, nlist, elistp)
int int
lock_get(lt, locker, flags, obj, lock_mode, lock) lock_get(lt, locker, flags, obj, lock_mode, lock)
DB_LOCKTAB *lt; DB_LOCKTAB *lt;
u_int32_t locker; u_int32_t locker, flags;
int flags;
const DBT *obj; const DBT *obj;
db_lockmode_t lock_mode; db_lockmode_t lock_mode;
DB_LOCK *lock; DB_LOCK *lock;
@ -496,35 +255,6 @@ lock_put(lt, lock)
return (ret); 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 static int
__lock_put_internal(lt, lockp, do_all) __lock_put_internal(lt, lockp, do_all)
DB_LOCKTAB *lt; DB_LOCKTAB *lt;
@ -593,7 +323,7 @@ __lock_put_internal(lt, lockp, do_all)
SH_TAILQ_INSERT_TAIL(&sh_obj->holders, lp_w, links); SH_TAILQ_INSERT_TAIL(&sh_obj->holders, lp_w, links);
/* Wake up waiter. */ /* 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; state_changed = 1;
} }
@ -626,8 +356,7 @@ __lock_put_internal(lt, lockp, do_all)
static int static int
__lock_get_internal(lt, locker, flags, obj, lock_mode, lockp) __lock_get_internal(lt, locker, flags, obj, lock_mode, lockp)
DB_LOCKTAB *lt; DB_LOCKTAB *lt;
u_int32_t locker; u_int32_t locker, flags;
int flags;
const DBT *obj; const DBT *obj;
db_lockmode_t lock_mode; db_lockmode_t lock_mode;
struct __db_lock **lockp; struct __db_lock **lockp;
@ -741,7 +470,7 @@ __lock_get_internal(lt, locker, flags, obj, lock_mode, lockp)
*/ */
(void)__db_mutex_init(&newl->mutex, (void)__db_mutex_init(&newl->mutex,
MUTEX_LOCK_OFFSET(lt->region, &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. * 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) if (lrp->detect != DB_LOCK_NORUN)
ret = lock_detect(lt, 0, lrp->detect); 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); LOCK_LOCKREGION(lt);
if (newl->status != DB_LSTAT_PENDING) { if (newl->status != DB_LSTAT_PENDING) {
@ -801,306 +530,6 @@ __lock_get_internal(lt, locker, flags, obj, lock_mode, lockp)
return (ret); return (ret);
} }
/*
* 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 -- * __lock_is_locked --
* *
@ -1136,7 +565,12 @@ __lock_is_locked(lt, locker, dbt, mode)
return (0); return (0);
} }
static void /*
* __lock_printlock --
*
* PUBLIC: void __lock_printlock __P((DB_LOCKTAB *, struct __db_lock *, int));
*/
void
__lock_printlock(lt, lp, ispgno) __lock_printlock(lt, lp, ispgno)
DB_LOCKTAB *lt; DB_LOCKTAB *lt;
struct __db_lock *lp; struct __db_lock *lp;
@ -1213,39 +647,6 @@ __lock_printlock(lt, lp, ispgno)
printf("\n"); 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 *, * PUBLIC: int __lock_getobj __P((DB_LOCKTAB *,
@ -1354,19 +755,7 @@ __lock_remove_waiter(lt, sh_obj, lockp, status)
lockp->status = status; lockp->status = status;
/* Wake whoever is waiting on this lock. */ /* Wake whoever is waiting on this lock. */
(void)__db_mutex_unlock(&lockp->mutex, lt->fd); (void)__db_mutex_unlock(&lockp->mutex, lt->reginfo.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);
} }
static void static void
@ -1384,17 +773,18 @@ __lock_checklocker(lt, lockp, do_remove)
if (__lock_getobj(lt, lockp->holder, NULL, DB_LOCK_LOCKER, &sh_locker) if (__lock_getobj(lt, lockp->holder, NULL, DB_LOCK_LOCKER, &sh_locker)
== 0 && SH_LIST_FIRST(&sh_locker->heldby, __db_lock) == NULL) { == 0 && SH_LIST_FIRST(&sh_locker->heldby, __db_lock) == NULL) {
__lock_freeobj(lt, sh_locker); __lock_freeobj(lt, sh_locker);
lt->region->nlockers--; lt->region->nlockers--;
} }
} }
static void static void
__lock_reset_region(lt) __lock_freeobj(lt, obj)
DB_LOCKTAB *lt; DB_LOCKTAB *lt;
DB_LOCKOBJ *obj;
{ {
lt->conflicts = (u_int8_t *)lt->region + sizeof(DB_LOCKREGION); HASHREMOVE_EL(lt->hashtab,
lt->hashtab = __db_lockobj, links, obj, lt->region->table_size, __lock_lhash);
(DB_HASHTAB *)((u_int8_t *)lt->region + lt->region->hash_off); if (obj->lockobj.size > sizeof(obj->objdata))
lt->mem = (void *)((u_int8_t *)lt->region + lt->region->mem_off); __db_shalloc_free(lt->mem, SH_DBT_PTR(&obj->lockobj));
lt->reg_size = lt->region->hdr.size; SH_TAILQ_INSERT_HEAD(&lt->region->free_objs, obj, links, __db_lockobj);
} }

View File

@ -1,14 +1,14 @@
/*- /*-
* See the file LICENSE for redistribution information. * See the file LICENSE for redistribution information.
* *
* Copyright (c) 1996, 1997 * Copyright (c) 1996, 1997, 1998
* Sleepycat Software. All rights reserved. * Sleepycat Software. All rights reserved.
*/ */
#include "config.h" #include "config.h"
#ifndef lint #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 */ #endif /* not lint */
#ifndef NO_SYSTEM_INCLUDES #ifndef NO_SYSTEM_INCLUDES

View File

@ -1,25 +1,21 @@
/*- /*-
* See the file LICENSE for redistribution information. * See the file LICENSE for redistribution information.
* *
* Copyright (c) 1996, 1997 * Copyright (c) 1996, 1997, 1998
* Sleepycat Software. All rights reserved. * Sleepycat Software. All rights reserved.
*/ */
#include "config.h" #include "config.h"
#ifndef lint #ifndef lint
static const char copyright[] = static const char sccsid[] = "@(#)lock_deadlock.c 10.32 (Sleepycat) 4/26/98";
"@(#) Copyright (c) 1997\n\ #endif /* not lint */
Sleepycat Software Inc. All rights reserved.\n";
static const char sccsid[] = "@(#)lock_deadlock.c 10.26 (Sleepycat) 11/25/97";
#endif
#ifndef NO_SYSTEM_INCLUDES #ifndef NO_SYSTEM_INCLUDES
#include <sys/types.h> #include <sys/types.h>
#include <errno.h> #include <errno.h>
#include <string.h> #include <string.h>
#include <stdlib.h>
#endif #endif
#include "db_int.h" #include "db_int.h"
@ -59,14 +55,14 @@ static int __dd_build
static u_int32_t static u_int32_t
*__dd_find __P((u_int32_t *, locker_info *, 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)); static void __dd_debug __P((DB_ENV *, locker_info *, u_int32_t *, u_int32_t));
#endif #endif
int int
lock_detect(lt, flags, atype) lock_detect(lt, flags, atype)
DB_LOCKTAB *lt; DB_LOCKTAB *lt;
int flags, atype; u_int32_t flags, atype;
{ {
DB_ENV *dbenv; DB_ENV *dbenv;
locker_info *idmap; locker_info *idmap;
@ -96,7 +92,7 @@ lock_detect(lt, flags, atype)
if (nlockers == 0) if (nlockers == 0)
return (0); return (0);
#ifdef DEBUG #ifdef DIAGNOSTIC
if (dbenv->db_verbose != 0) if (dbenv->db_verbose != 0)
__dd_debug(dbenv, idmap, bitmap, nlockers); __dd_debug(dbenv, idmap, bitmap, nlockers);
#endif #endif
@ -202,7 +198,7 @@ __dd_build(dbenv, bmp, nlockers, idmap)
u_int8_t *pptr; u_int8_t *pptr;
locker_info *id_array; locker_info *id_array;
u_int32_t *bitmap, count, *entryp, i, id, nentries, *tmpmap; u_int32_t *bitmap, count, *entryp, i, id, nentries, *tmpmap;
int is_first, ret; int is_first;
lt = dbenv->lk_info; lt = dbenv->lk_info;
@ -322,8 +318,8 @@ retry: count = lt->region->nlockers;
lp != NULL; lp != NULL;
is_first = 0, is_first = 0,
lp = SH_TAILQ_NEXT(lp, links, __db_lock)) { lp = SH_TAILQ_NEXT(lp, links, __db_lock)) {
if ((ret = __lock_getobj(lt, lp->holder, if (__lock_getobj(lt, lp->holder,
NULL, DB_LOCK_LOCKER, &lockerp)) != 0) { NULL, DB_LOCK_LOCKER, &lockerp) != 0) {
__db_err(dbenv, __db_err(dbenv,
"warning unable to find object"); "warning unable to find object");
continue; continue;
@ -357,8 +353,8 @@ retry: count = lt->region->nlockers;
for (id = 0; id < count; id++) { for (id = 0; id < count; id++) {
if (!id_array[id].valid) if (!id_array[id].valid)
continue; continue;
if ((ret = __lock_getobj(lt, if (__lock_getobj(lt,
id_array[id].id, NULL, DB_LOCK_LOCKER, &lockerp)) != 0) { id_array[id].id, NULL, DB_LOCK_LOCKER, &lockerp) != 0) {
__db_err(dbenv, __db_err(dbenv,
"No locks for locker %lu", (u_long)id_array[id].id); "No locks for locker %lu", (u_long)id_array[id].id);
continue; continue;
@ -448,7 +444,7 @@ __dd_abort(dbenv, info)
SH_LIST_REMOVE(lockp, locker_links, __db_lock); SH_LIST_REMOVE(lockp, locker_links, __db_lock);
sh_obj = (DB_LOCKOBJ *)((u_int8_t *)lockp + lockp->obj); sh_obj = (DB_LOCKOBJ *)((u_int8_t *)lockp + lockp->obj);
SH_TAILQ_REMOVE(&sh_obj->waiters, lockp, links, __db_lock); 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; ret = 0;
@ -456,7 +452,7 @@ out: UNLOCK_LOCKREGION(lt);
return (ret); return (ret);
} }
#ifdef DEBUG #ifdef DIAGNOSTIC
static void static void
__dd_debug(dbenv, idmap, bitmap, nlockers) __dd_debug(dbenv, idmap, bitmap, nlockers)
DB_ENV *dbenv; DB_ENV *dbenv;

726
db2/lock/lock_region.c Normal file
View File

@ -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");
}

View File

@ -1,25 +1,20 @@
/*- /*-
* See the file LICENSE for redistribution information. * See the file LICENSE for redistribution information.
* *
* Copyright (c) 1996, 1997 * Copyright (c) 1996, 1997, 1998
* Sleepycat Software. All rights reserved. * Sleepycat Software. All rights reserved.
*/ */
#include "config.h" #include "config.h"
#ifndef lint #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 */ #endif /* not lint */
#ifndef NO_SYSTEM_INCLUDES #ifndef NO_SYSTEM_INCLUDES
#include <sys/types.h> #include <sys/types.h>
#include <fcntl.h>
#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h> #include <string.h>
#include <unistd.h>
#endif #endif
#include "db_int.h" #include "db_int.h"
@ -30,11 +25,13 @@ static const char sccsid[] = "@(#)lock_util.c 10.5 (Sleepycat) 1/8/98";
#include "lock.h" #include "lock.h"
/* /*
* This function is used to compare a DBT that is about to be entered * __lock_cmp --
* into a hash table with an object already in the hash table. Note * This function is used to compare a DBT that is about to be entered
* that it just returns true on equal and 0 on not-equal. Therefore this * into a hash table with an object already in the hash table. Note
* cannot be used as a sort function; its purpose is to be used as a * that it just returns true on equal and 0 on not-equal. Therefore
* hash comparison function. * 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 *)); * PUBLIC: int __lock_cmp __P((const DBT *, DB_LOCKOBJ *));
*/ */
int int
@ -46,6 +43,7 @@ __lock_cmp(dbt, lock_obj)
if (lock_obj->type != DB_LOCK_OBJTYPE) if (lock_obj->type != DB_LOCK_OBJTYPE)
return (0); return (0);
obj_data = SH_DBT_PTR(&lock_obj->lockobj); obj_data = SH_DBT_PTR(&lock_obj->lockobj);
return (dbt->size == lock_obj->lockobj.size && return (dbt->size == lock_obj->lockobj.size &&
memcmp(dbt->data, obj_data, dbt->size) == 0); 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 #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); \
}
/*
* __lock_ohash --
*
* PUBLIC: u_int32_t __lock_ohash __P((const DBT *));
*/
u_int32_t
__lock_ohash(dbt) __lock_ohash(dbt)
const DBT *dbt; const DBT *dbt;
{ {
if (dbt->size == sizeof(struct __db_ilock))
FAST_HASH(dbt->data);
return (__ham_func5(dbt->data, dbt->size)); return (__ham_func5(dbt->data, dbt->size));
} }
/* /*
* PUBLIC: u_int32_t __lock_locker_hash __P((u_int32_t)); * __lock_lhash --
*/ *
u_int32_t
__lock_locker_hash(locker)
u_int32_t locker;
{
return (__ham_func5(&locker, sizeof(locker)));
}
/*
* PUBLIC: u_int32_t __lock_lhash __P((DB_LOCKOBJ *)); * PUBLIC: u_int32_t __lock_lhash __P((DB_LOCKOBJ *));
*/ */
u_int32_t u_int32_t
__lock_lhash(lock_obj) __lock_lhash(lock_obj)
DB_LOCKOBJ *lock_obj; DB_LOCKOBJ *lock_obj;
{ {
u_int32_t tmp;
void *obj_data; void *obj_data;
obj_data = SH_DBT_PTR(&lock_obj->lockobj); 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)); 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);
}

View File

@ -1,21 +1,19 @@
/*- /*-
* See the file LICENSE for redistribution information. * See the file LICENSE for redistribution information.
* *
* Copyright (c) 1996, 1997 * Copyright (c) 1996, 1997, 1998
* Sleepycat Software. All rights reserved. * Sleepycat Software. All rights reserved.
*/ */
#include "config.h" #include "config.h"
#ifndef lint #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 */ #endif /* not lint */
#ifndef NO_SYSTEM_INCLUDES #ifndef NO_SYSTEM_INCLUDES
#include <sys/types.h> #include <sys/types.h>
#include <sys/stat.h>
#include <errno.h> #include <errno.h>
#include <fcntl.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <unistd.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 "db_int.h"
#include "shqueue.h" #include "shqueue.h"
#include "db_shash.h"
#include "log.h" #include "log.h"
#include "db_dispatch.h" #include "db_dispatch.h"
#include "txn_auto.h" #include "txn_auto.h"
@ -38,15 +35,14 @@ static int __log_recover __P((DB_LOG *));
int int
log_open(path, flags, mode, dbenv, lpp) log_open(path, flags, mode, dbenv, lpp)
const char *path; const char *path;
int flags; u_int32_t flags;
int mode; int mode;
DB_ENV *dbenv; DB_ENV *dbenv;
DB_LOG **lpp; DB_LOG **lpp;
{ {
DB_LOG *dblp; DB_LOG *dblp;
LOG *lp; LOG *lp;
size_t len; int ret;
int fd, newregion, ret, retry_cnt;
/* Validate arguments. */ /* Validate arguments. */
#ifdef HAVE_SPINLOCKS #ifdef HAVE_SPINLOCKS
@ -57,22 +53,13 @@ log_open(path, flags, mode, dbenv, lpp)
if ((ret = __db_fchk(dbenv, "log_open", flags, OKFLAGS)) != 0) if ((ret = __db_fchk(dbenv, "log_open", flags, OKFLAGS)) != 0)
return (ret); 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. */ /* Create and initialize the DB_LOG structure. */
if ((dblp = (DB_LOG *)__db_calloc(1, sizeof(DB_LOG))) == NULL) if ((dblp = (DB_LOG *)__db_calloc(1, sizeof(DB_LOG))) == NULL)
return (ENOMEM); return (ENOMEM);
if (path != NULL && (dblp->dir = __db_strdup(path)) == NULL) { if (path != NULL && (dblp->dir = __db_strdup(path)) == NULL) {
__db_free(dblp); ret = ENOMEM;
return (ENOMEM); goto err;
} }
dblp->dbenv = dbenv; 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 * file names there. Make it fairly large so that we don't have to
* grow it. * grow it.
*/ */
len = 30 * 1024; #define DEF_LOG_SIZE (30 * 1024)
/* Map in the region. */ /* Map in the region. */
retry_cnt = newregion = 0; dblp->reginfo.dbenv = dbenv;
retry: if (LF_ISSET(DB_CREATE)) { dblp->reginfo.appname = DB_APP_LOG;
ret = __db_rcreate(dbenv, DB_APP_LOG, path, if (path == NULL)
DB_DEFAULT_LOG_FILE, mode, len, 0, &fd, &dblp->maddr); dblp->reginfo.path = NULL;
if (ret == 0) { else
/* Put the LOG structure first in the region. */ if ((dblp->reginfo.path = __db_strdup(path)) == NULL)
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)
goto err; goto err;
} dblp->reginfo.file = DB_DEFAULT_LOG_FILE;
dblp->reginfo.mode = mode;
/* If we didn't or couldn't create the region, try and join it. */ dblp->reginfo.size = DEF_LOG_SIZE;
if (!newregion && dblp->reginfo.dbflags = flags;
(ret = __db_ropen(dbenv, DB_APP_LOG, dblp->reginfo.flags = REGION_SIZEDEF;
path, DB_DEFAULT_LOG_FILE, 0, &fd, &dblp->maddr)) != 0) { if ((ret = __db_rattach(&dblp->reginfo)) != 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;
}
goto err; goto err;
/*
* 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;
} }
/* Set up the common information. */ /* Initialize thread information, mutex. */
dblp->lp = dblp->maddr;
dblp->addr = (u_int8_t *)dblp->maddr + sizeof(LOG);
dblp->fd = fd;
/* Initialize thread information. */
if (LF_ISSET(DB_THREAD)) { if (LF_ISSET(DB_THREAD)) {
F_SET(dblp, DB_AM_THREAD); F_SET(dblp, DB_AM_THREAD);
if (!newregion)
LOCK_LOGREGION(dblp);
if ((ret = __db_shalloc(dblp->addr, if ((ret = __db_shalloc(dblp->addr,
sizeof(db_mutex_t), MUTEX_ALIGNMENT, &dblp->mutexp)) == 0) sizeof(db_mutex_t), MUTEX_ALIGNMENT, &dblp->mutexp)) != 0)
(void)__db_mutex_init(dblp->mutexp, -1); goto err;
if (!newregion) (void)__db_mutex_init(dblp->mutexp, -1);
UNLOCK_LOGREGION(dblp);
if (ret != 0) {
(void)log_close(dblp);
if (newregion)
(void)log_unlink(path, 1, dbenv);
return (ret);
}
} }
/* /*
* If doing recovery, try and recover any previous log files * If doing recovery, try and recover any previous log files before
* before releasing the lock. * releasing the lock.
*/ */
if (newregion) { if (F_ISSET(&dblp->reginfo, REGION_CREATED) &&
ret = __log_recover(dblp); (ret = __log_recover(dblp)) != 0)
UNLOCK_LOGREGION(dblp); goto err;
if (ret != 0) { UNLOCK_LOGREGION(dblp);
(void)log_close(dblp);
(void)log_unlink(path, 1, dbenv);
return (ret);
}
}
*lpp = dblp; *lpp = dblp;
return (0); return (0);
err: /* err: if (dblp->reginfo.addr != NULL) {
* We never get here with an allocated thread-mutex, so we do if (dblp->mutexp != NULL)
* not have to worry about freeing it. __db_shalloc_free(dblp->addr, dblp->mutexp);
*/
FREE(dblp, sizeof(DB_LOG));
return (ret);
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; continue;
memcpy(&chk, dbt.data, sizeof(u_int32_t)); memcpy(&chk, dbt.data, sizeof(u_int32_t));
if (chk == DB_txn_ckp) { if (chk == DB_txn_ckp) {
lp->c_lsn = lsn; lp->chkpt_lsn = lsn;
found_checkpoint = 1; found_checkpoint = 1;
} }
} }
@ -273,7 +245,7 @@ __log_recover(dblp)
continue; continue;
memcpy(&chk, dbt.data, sizeof(u_int32_t)); memcpy(&chk, dbt.data, sizeof(u_int32_t));
if (chk == DB_txn_ckp) { if (chk == DB_txn_ckp) {
lp->c_lsn = lsn; lp->chkpt_lsn = lsn;
found_checkpoint = 1; found_checkpoint = 1;
} }
} }
@ -281,7 +253,7 @@ __log_recover(dblp)
/* If we never find a checkpoint, that's okay, just 0 it out. */ /* If we never find a checkpoint, that's okay, just 0 it out. */
if (!found_checkpoint) if (!found_checkpoint)
ZERO_LSN(lp->c_lsn); ZERO_LSN(lp->chkpt_lsn);
__db_err(dblp->dbenv, __db_err(dblp->dbenv,
"Recovering the log: last valid LSN: file: %lu offset %lu", "Recovering the log: last valid LSN: file: %lu offset %lu",
@ -380,7 +352,7 @@ __log_valid(dblp, lp, cnt)
if ((ret = __db_open(p, if ((ret = __db_open(p,
DB_RDONLY | DB_SEQUENTIAL, DB_RDONLY | DB_SEQUENTIAL,
DB_RDONLY | DB_SEQUENTIAL, 0, &fd)) != 0 || 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 || (ret = __db_read(fd, &persist, sizeof(LOGP), &nw)) != 0 ||
nw != sizeof(LOGP)) { nw != sizeof(LOGP)) {
if (ret == 0) if (ret == 0)
@ -429,8 +401,6 @@ log_close(dblp)
{ {
int ret, t_ret; int ret, t_ret;
ret = 0;
/* Discard the per-thread pointer. */ /* Discard the per-thread pointer. */
if (dblp->mutexp != NULL) { if (dblp->mutexp != NULL) {
LOCK_LOGREGION(dblp); LOCK_LOGREGION(dblp);
@ -439,9 +409,7 @@ log_close(dblp)
} }
/* Close the region. */ /* Close the region. */
if ((t_ret = ret = __db_rdetach(&dblp->reginfo);
__db_rclose(dblp->dbenv, dblp->fd, dblp->maddr)) != 0 && ret == 0)
ret = t_ret;
/* Close open files, release allocated memory. */ /* Close open files, release allocated memory. */
if (dblp->lfd != -1 && (t_ret = __db_close(dblp->lfd)) != 0 && ret == 0) if (dblp->lfd != -1 && (t_ret = __db_close(dblp->lfd)) != 0 && ret == 0)
@ -456,8 +424,9 @@ log_close(dblp)
if (dblp->dir != NULL) if (dblp->dir != NULL)
FREES(dblp->dir); FREES(dblp->dir);
/* Free the structure. */ if (dblp->reginfo.path != NULL)
FREE(dblp, sizeof(DB_LOG)); FREES(dblp->reginfo.path);
FREE(dblp, sizeof(*dblp));
return (ret); return (ret);
} }
@ -472,8 +441,19 @@ log_unlink(path, force, dbenv)
int force; int force;
DB_ENV *dbenv; DB_ENV *dbenv;
{ {
return (__db_runlink(dbenv, REGINFO reginfo;
DB_APP_LOG, path, DB_DEFAULT_LOG_FILE, force)); 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_file = lp->lsn.file;
(*gspp)->st_cur_offset = lp->lsn.offset; (*gspp)->st_cur_offset = lp->lsn.offset;
(*gspp)->st_refcnt = lp->rlayout.refcnt;
(*gspp)->st_regsize = lp->rlayout.size;
UNLOCK_LOGREGION(dblp); UNLOCK_LOGREGION(dblp);
return (0); return (0);

View File

@ -1,43 +1,12 @@
/*- /*-
* See the file LICENSE for redistribution information. * See the file LICENSE for redistribution information.
* *
* Copyright (c) 1996, 1997 * Copyright (c) 1996, 1997, 1998
* Sleepycat Software. All rights reserved. * Sleepycat Software. All rights reserved.
* *
* @(#)log.src 10.4 (Sleepycat) 1/17/98 * @(#)log.src 10.5 (Sleepycat) 4/10/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
*/ */
/*
* Use the argument of PREFIX as the prefix for all record types,
* routines, id numbers, etc.
*/
PREFIX log PREFIX log
/* Used for registering name/id translations at open or close. */ /* Used for registering name/id translations at open or close. */

View File

@ -1,14 +1,14 @@
/*- /*-
* See the file LICENSE for redistribution information. * See the file LICENSE for redistribution information.
* *
* Copyright (c) 1997 * Copyright (c) 1997, 1998
* Sleepycat Software. All rights reserved. * Sleepycat Software. All rights reserved.
*/ */
#include "config.h" #include "config.h"
#ifndef lint #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 */ #endif /* not lint */
#ifndef NO_SYSTEM_INCLUDES #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 "db_dispatch.h"
#include "shqueue.h" #include "shqueue.h"
#include "log.h" #include "log.h"
#include "clib_ext.h"
#include "common_ext.h" #include "common_ext.h"
#include "clib_ext.h" /* XXX: needed for getcwd. */
static int __absname __P((char *, char *, char **)); static int __absname __P((char *, char *, char **));
static int __build_data __P((DB_LOG *, char *, char ***, void *(*)(size_t))); static int __build_data __P((DB_LOG *, char *, char ***, void *(*)(size_t)));
@ -40,7 +40,7 @@ int
log_archive(dblp, listp, flags, db_malloc) log_archive(dblp, listp, flags, db_malloc)
DB_LOG *dblp; DB_LOG *dblp;
char ***listp; char ***listp;
int flags; u_int32_t flags;
void *(*db_malloc) __P((size_t)); void *(*db_malloc) __P((size_t));
{ {
DBT rec; DBT rec;
@ -89,6 +89,11 @@ log_archive(dblp, listp, flags, db_malloc)
break; break;
case 0: case 0:
if ((ret = __log_findckp(dblp, &stable_lsn)) != 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) if (ret != DB_NOTFOUND)
return (ret); return (ret);
*listp = NULL; *listp = NULL;
@ -269,7 +274,7 @@ lg_free: if (F_ISSET(&rec, DB_DBT_MALLOC) && rec.data != NULL)
/* Get the real name. */ /* Get the real name. */
if ((ret = __db_appname(dblp->dbenv, 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; goto err2;
/* If the file doesn't exist, ignore it. */ /* If the file doesn't exist, ignore it. */
@ -335,21 +340,25 @@ __absname(pref, name, newnamep)
char *pref, *name, **newnamep; char *pref, *name, **newnamep;
{ {
size_t l_pref, l_name; size_t l_pref, l_name;
int isabspath;
char *newname; char *newname;
l_pref = strlen(pref);
l_name = strlen(name); l_name = strlen(name);
isabspath = __db_abspath(name);
l_pref = isabspath ? 0 : strlen(pref);
/* Malloc space for concatenating the two. */ /* 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); return (ENOMEM);
/* Build the name. */ /* Build the name. If `name' is an absolute path, ignore any prefix. */
memcpy(newname, pref, l_pref); if (!isabspath) {
if (strchr(PATH_SEPARATOR, newname[l_pref - 1]) == NULL) memcpy(newname, pref, l_pref);
newname[l_pref++] = PATH_SEPARATOR[0]; if (strchr(PATH_SEPARATOR, newname[l_pref - 1]) == NULL)
newname[l_pref++] = PATH_SEPARATOR[0];
}
memcpy(newname + l_pref, name, l_name + 1); memcpy(newname + l_pref, name, l_name + 1);
*newnamep = newname;
return (0); return (0);
} }
@ -409,5 +418,5 @@ static int
__cmpfunc(p1, p2) __cmpfunc(p1, p2)
const void *p1, *p2; const void *p1, *p2;
{ {
return (strcmp(*((char **)p1), *((char **)p2))); return (strcmp(*((char * const *)p1), *((char * const *)p2)));
} }

View File

@ -15,8 +15,6 @@
#include "db_dispatch.h" #include "db_dispatch.h"
#include "log.h" #include "log.h"
#include "db_am.h" #include "db_am.h"
#include "common_ext.h"
/* /*
* PUBLIC: int __log_register_log * PUBLIC: int __log_register_log
* PUBLIC: __P((DB_LOG *, DB_TXN *, DB_LSN *, u_int32_t, * 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); bp += sizeof(id);
memcpy(bp, &ftype, sizeof(ftype)); memcpy(bp, &ftype, sizeof(ftype));
bp += sizeof(ftype); bp += sizeof(ftype);
#ifdef DEBUG #ifdef DIAGNOSTIC
if ((u_int32_t)(bp - (u_int8_t *)logrec.data) != logrec.size) if ((u_int32_t)(bp - (u_int8_t *)logrec.data) != logrec.size)
fprintf(stderr, "Error in log record length"); fprintf(stderr, "Error in log record length");
#endif #endif
@ -108,22 +106,23 @@ int __log_register_log(logp, txnid, ret_lsnp, flags,
* PUBLIC: __P((DB_LOG *, DBT *, DB_LSN *, int, void *)); * PUBLIC: __P((DB_LOG *, DBT *, DB_LSN *, int, void *));
*/ */
int int
__log_register_print(notused1, dbtp, lsnp, notused3, notused4) __log_register_print(notused1, dbtp, lsnp, notused2, notused3)
DB_LOG *notused1; DB_LOG *notused1;
DBT *dbtp; DBT *dbtp;
DB_LSN *lsnp; DB_LSN *lsnp;
int notused3; int notused2;
void *notused4; void *notused3;
{ {
__log_register_args *argp; __log_register_args *argp;
u_int32_t i; u_int32_t i;
int c, ret; u_int ch;
int ret;
i = 0; i = 0;
c = 0; ch = 0;
notused1 = NULL; notused1 = NULL;
notused3 = 0; notused2 = 0;
notused4 = NULL; notused3 = NULL;
if ((ret = __log_register_read(dbtp->data, &argp)) != 0) if ((ret = __log_register_read(dbtp->data, &argp)) != 0)
return (ret); return (ret);
@ -137,20 +136,20 @@ __log_register_print(notused1, dbtp, lsnp, notused3, notused4)
printf("\topcode: %lu\n", (u_long)argp->opcode); printf("\topcode: %lu\n", (u_long)argp->opcode);
printf("\tname: "); printf("\tname: ");
for (i = 0; i < argp->name.size; i++) { for (i = 0; i < argp->name.size; i++) {
c = ((char *)argp->name.data)[i]; ch = ((u_int8_t *)argp->name.data)[i];
if (isprint(c) || c == 0xa) if (isprint(ch) || ch == 0xa)
putchar(c); putchar(ch);
else else
printf("%#x ", c); printf("%#x ", ch);
} }
printf("\n"); printf("\n");
printf("\tuid: "); printf("\tuid: ");
for (i = 0; i < argp->uid.size; i++) { for (i = 0; i < argp->uid.size; i++) {
c = ((char *)argp->uid.data)[i]; ch = ((u_int8_t *)argp->uid.data)[i];
if (isprint(c) || c == 0xa) if (isprint(ch) || ch == 0xa)
putchar(c); putchar(ch);
else else
printf("%#x ", c); printf("%#x ", ch);
} }
printf("\n"); printf("\n");
printf("\tid: %lu\n", (u_long)argp->id); printf("\tid: %lu\n", (u_long)argp->id);

View File

@ -1,13 +1,13 @@
/*- /*-
* See the file LICENSE for redistribution information. * See the file LICENSE for redistribution information.
* *
* Copyright (c) 1996, 1997 * Copyright (c) 1996, 1997, 1998
* Sleepycat Software. All rights reserved. * Sleepycat Software. All rights reserved.
*/ */
#include "config.h" #include "config.h"
#ifndef lint #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 */ #endif /* not lint */
#ifndef NO_SYSTEM_INCLUDES #ifndef NO_SYSTEM_INCLUDES

View File

@ -1,21 +1,20 @@
/*- /*-
* See the file LICENSE for redistribution information. * See the file LICENSE for redistribution information.
* *
* Copyright (c) 1996, 1997 * Copyright (c) 1996, 1997, 1998
* Sleepycat Software. All rights reserved. * Sleepycat Software. All rights reserved.
*/ */
#include "config.h" #include "config.h"
#ifndef lint #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 */ #endif /* not lint */
#ifndef NO_SYSTEM_INCLUDES #ifndef NO_SYSTEM_INCLUDES
#include <sys/types.h> #include <sys/types.h>
#include <errno.h> #include <errno.h>
#include <stdlib.h>
#include <string.h> #include <string.h>
#endif #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 * We find one at 500. This means that we can truncate the log before
* 500 or run recovery beginning at 500. * 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 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 *)); * PUBLIC: int __log_findckp __P((DB_LOG *, DB_LSN *));
*/ */
@ -70,9 +69,12 @@ __log_findckp(lp, lsnp)
memset(&data, 0, sizeof(data)); memset(&data, 0, sizeof(data));
if (F_ISSET(lp, DB_AM_THREAD)) if (F_ISSET(lp, DB_AM_THREAD))
F_SET(&data, DB_DBT_MALLOC); 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); 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; next_lsn = last_ckp;
do { do {
@ -115,16 +117,12 @@ __log_findckp(lp, lsnp)
* beginning of the log. * beginning of the log.
*/ */
if (log_compare(&last_ckp, &ckp_lsn) > 0) { 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); return (ret);
if (F_ISSET(lp, DB_AM_THREAD)) if (F_ISSET(lp, DB_AM_THREAD))
__db_free(data.data); __db_free(data.data);
} }
*lsnp = last_ckp; *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); return (IS_ZERO_LSN(last_ckp) ? DB_NOTFOUND : 0);
} }

View File

@ -1,21 +1,19 @@
/*- /*-
* See the file LICENSE for redistribution information. * See the file LICENSE for redistribution information.
* *
* Copyright (c) 1996, 1997 * Copyright (c) 1996, 1997, 1998
* Sleepycat Software. All rights reserved. * Sleepycat Software. All rights reserved.
*/ */
#include "config.h" #include "config.h"
#ifndef lint #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 */ #endif /* not lint */
#ifndef NO_SYSTEM_INCLUDES #ifndef NO_SYSTEM_INCLUDES
#include <sys/types.h> #include <sys/types.h>
#include <errno.h> #include <errno.h>
#include <fcntl.h>
#include <stdlib.h>
#include <string.h> #include <string.h>
#include <unistd.h> #include <unistd.h>
#endif #endif
@ -36,9 +34,8 @@ log_get(dblp, alsn, dbt, flags)
DB_LOG *dblp; DB_LOG *dblp;
DB_LSN *alsn; DB_LSN *alsn;
DBT *dbt; DBT *dbt;
int flags; u_int32_t flags;
{ {
LOG *lp;
int ret; int ret;
/* Validate arguments. */ /* Validate arguments. */
@ -66,8 +63,6 @@ log_get(dblp, alsn, dbt, flags)
return (__db_ferr(dblp->dbenv, "threaded data", 1)); return (__db_ferr(dblp->dbenv, "threaded data", 1));
} }
lp = dblp->lp;
LOCK_LOGREGION(dblp); LOCK_LOGREGION(dblp);
/* /*
@ -97,14 +92,15 @@ log_get(dblp, alsn, dbt, flags)
* __log_get -- * __log_get --
* Get a log record; internal version. * 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 int
__log_get(dblp, alsn, dbt, flags, silent) __log_get(dblp, alsn, dbt, flags, silent)
DB_LOG *dblp; DB_LOG *dblp;
DB_LSN *alsn; DB_LSN *alsn;
DBT *dbt; DBT *dbt;
int flags, silent; u_int32_t flags;
int silent;
{ {
DB_LSN nlsn; DB_LSN nlsn;
HDR hdr; HDR hdr;
@ -122,7 +118,7 @@ __log_get(dblp, alsn, dbt, flags, silent)
nlsn = dblp->c_lsn; nlsn = dblp->c_lsn;
switch (flags) { switch (flags) {
case DB_CHECKPOINT: case DB_CHECKPOINT:
nlsn = lp->c_lsn; nlsn = lp->chkpt_lsn;
if (IS_ZERO_LSN(nlsn)) { if (IS_ZERO_LSN(nlsn)) {
__db_err(dblp->dbenv, __db_err(dblp->dbenv,
"log_get: unable to find checkpoint record: no checkpoint set."); "log_get: unable to find checkpoint record: no checkpoint set.");
@ -219,7 +215,8 @@ retry:
} }
/* Seek to the header offset and read the header. */ /* 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"; fail = "seek";
goto err1; goto err1;
} }
@ -272,7 +269,13 @@ retry:
goto cksum; 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) { if ((tbuf = (char *)__db_malloc(len)) == NULL) {
ret = ENOMEM; ret = ENOMEM;
goto err1; goto err1;

View File

@ -1,21 +1,19 @@
/*- /*-
* See the file LICENSE for redistribution information. * See the file LICENSE for redistribution information.
* *
* Copyright (c) 1996, 1997 * Copyright (c) 1996, 1997, 1998
* Sleepycat Software. All rights reserved. * Sleepycat Software. All rights reserved.
*/ */
#include "config.h" #include "config.h"
#ifndef lint #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 */ #endif /* not lint */
#ifndef NO_SYSTEM_INCLUDES #ifndef NO_SYSTEM_INCLUDES
#include <sys/types.h> #include <sys/types.h>
#include <errno.h> #include <errno.h>
#include <fcntl.h>
#include <stdlib.h>
#include <string.h> #include <string.h>
#include <time.h> #include <time.h>
#include <unistd.h> #include <unistd.h>
@ -43,18 +41,19 @@ log_put(dblp, lsn, dbt, flags)
DB_LOG *dblp; DB_LOG *dblp;
DB_LSN *lsn; DB_LSN *lsn;
const DBT *dbt; const DBT *dbt;
int flags; u_int32_t flags;
{ {
int ret; int ret;
/* Validate arguments. */ /* Validate arguments. */
#define OKFLAGS (DB_CHECKPOINT | DB_FLUSH) #define OKFLAGS (DB_CHECKPOINT | DB_FLUSH | DB_CURLSN)
if (flags != 0) { if (flags != 0) {
if ((ret = if ((ret =
__db_fchk(dblp->dbenv, "log_put", flags, OKFLAGS)) != 0) __db_fchk(dblp->dbenv, "log_put", flags, OKFLAGS)) != 0)
return (ret); return (ret);
switch (flags) { switch (flags) {
case DB_CHECKPOINT: case DB_CHECKPOINT:
case DB_CURLSN:
case DB_FLUSH: case DB_FLUSH:
case 0: case 0:
break; break;
@ -73,14 +72,14 @@ log_put(dblp, lsn, dbt, flags)
* __log_put -- * __log_put --
* Write a log record; internal version. * 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 int
__log_put(dblp, lsn, dbt, flags) __log_put(dblp, lsn, dbt, flags)
DB_LOG *dblp; DB_LOG *dblp;
DB_LSN *lsn; DB_LSN *lsn;
const DBT *dbt; const DBT *dbt;
int flags; u_int32_t flags;
{ {
DBT fid_dbt, t; DBT fid_dbt, t;
DB_LSN r_unused; DB_LSN r_unused;
@ -91,6 +90,17 @@ __log_put(dblp, lsn, dbt, flags)
lp = dblp->lp; 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 this information won't fit in the file, swap files. */
if (lp->lsn.offset + sizeof(HDR) + dbt->size > lp->persist.lg_max) { if (lp->lsn.offset + sizeof(HDR) + dbt->size > lp->persist.lg_max) {
if (sizeof(HDR) + if (sizeof(HDR) +
@ -151,7 +161,7 @@ __log_put(dblp, lsn, dbt, flags)
* Append the set of file name information into the log. * Append the set of file name information into the log.
*/ */
if (flags == DB_CHECKPOINT) { if (flags == DB_CHECKPOINT) {
lp->c_lsn = *lsn; lp->chkpt_lsn = *lsn;
for (fnp = SH_TAILQ_FIRST(&dblp->lp->fq, __fname); for (fnp = SH_TAILQ_FIRST(&dblp->lp->fq, __fname);
fnp != NULL; fnp = SH_TAILQ_NEXT(fnp, q, __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.data = R_ADDR(dblp, fnp->name_off);
t.size = strlen(t.data) + 1; t.size = strlen(t.data) + 1;
memset(&fid_dbt, 0, sizeof(fid_dbt)); 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; fid_dbt.size = DB_FILE_ID_LEN;
if ((ret = __log_register_log(dblp, NULL, &r_unused, 0, if ((ret = __log_register_log(dblp, NULL, &r_unused, 0,
LOG_CHECKPOINT, &t, &fid_dbt, fnp->id, fnp->s_type)) LOG_CHECKPOINT, &t, &fid_dbt, fnp->id, fnp->s_type))
@ -324,7 +334,11 @@ __log_flush(dblp, lsn)
*/ */
lp->s_lsn = lp->f_lsn; lp->s_lsn = lp->f_lsn;
if (!current) 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); return (0);
} }
@ -416,7 +430,7 @@ __log_write(dblp, addr, len)
* Seek to the offset in the file (someone may have written it * Seek to the offset in the file (someone may have written it
* since we last did). * 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); return (ret);
if ((ret = __db_write(dblp->lfd, addr, len, &nw)) != 0) if ((ret = __db_write(dblp->lfd, addr, len, &nw)) != 0)
return (ret); return (ret);
@ -461,7 +475,7 @@ log_file(dblp, lsn, namep, len)
return (ret); return (ret);
/* Check to make sure there's enough room and copy the name. */ /* Check to make sure there's enough room and copy the name. */
if (len < strlen(p)) { if (len < strlen(p) + 1) {
*namep = '\0'; *namep = '\0';
return (ENOMEM); return (ENOMEM);
} }
@ -518,5 +532,5 @@ __log_name(dblp, filenumber, namep)
(void)snprintf(name, sizeof(name), LFNAME, filenumber); (void)snprintf(name, sizeof(name), LFNAME, filenumber);
return (__db_appname(dblp->dbenv, return (__db_appname(dblp->dbenv,
DB_APP_LOG, dblp->dir, name, NULL, namep)); DB_APP_LOG, dblp->dir, name, 0, NULL, namep));
} }

View File

@ -1,7 +1,7 @@
/*- /*-
* See the file LICENSE for redistribution information. * See the file LICENSE for redistribution information.
* *
* Copyright (c) 1996, 1997 * Copyright (c) 1996, 1997, 1998
* Sleepycat Software. All rights reserved. * Sleepycat Software. All rights reserved.
*/ */
/* /*
@ -40,16 +40,13 @@
#include "config.h" #include "config.h"
#ifndef lint #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 */ #endif /* not lint */
#ifndef NO_SYSTEM_INCLUDES #ifndef NO_SYSTEM_INCLUDES
#include <sys/types.h> #include <sys/types.h>
#include <errno.h> #include <errno.h>
#include <fcntl.h>
#include <stddef.h>
#include <stdlib.h>
#include <string.h> #include <string.h>
#endif #endif
@ -90,7 +87,7 @@ __log_register_recover(logp, dbtp, lsnp, redo, info)
if ((argp->opcode == LOG_CHECKPOINT && redo == TXN_OPENFILES) || if ((argp->opcode == LOG_CHECKPOINT && redo == TXN_OPENFILES) ||
(argp->opcode == LOG_OPEN && (argp->opcode == LOG_OPEN &&
(redo == TXN_REDO || redo == TXN_OPENFILES || (redo == TXN_REDO || redo == TXN_OPENFILES ||
redo == TXN_FORWARD_ROLL)) || redo == TXN_FORWARD_ROLL)) ||
(argp->opcode == LOG_CLOSE && (argp->opcode == LOG_CLOSE &&
(redo == TXN_UNDO || redo == TXN_BACKWARD_ROLL))) { (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) if (!logp->dbentry[argp->id].deleted)
ret = EINVAL; ret = EINVAL;
} else if (--logp->dbentry[argp->id].refcount == 0) { } 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( ret = logp->dbentry[argp->id].dbp->close(
logp->dbentry[argp->id].dbp, 0); logp->dbentry[argp->id].dbp, 0);
logp->dbentry[argp->id].dbp = NULL; logp->dbentry[argp->id].dbp = NULL;

View File

@ -1,20 +1,19 @@
/*- /*-
* See the file LICENSE for redistribution information. * See the file LICENSE for redistribution information.
* *
* Copyright (c) 1996, 1997 * Copyright (c) 1996, 1997, 1998
* Sleepycat Software. All rights reserved. * Sleepycat Software. All rights reserved.
*/ */
#include "config.h" #include "config.h"
#ifndef lint #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 */ #endif /* not lint */
#ifndef NO_SYSTEM_INCLUDES #ifndef NO_SYSTEM_INCLUDES
#include <sys/types.h> #include <sys/types.h>
#include <errno.h> #include <errno.h>
#include <stdlib.h>
#include <string.h> #include <string.h>
#endif #endif
@ -42,12 +41,12 @@ log_register(dblp, dbp, name, type, idp)
u_int32_t fid; u_int32_t fid;
int inserted, ret; int inserted, ret;
char *fullname; char *fullname;
void *fidp, *namep; void *namep;
fid = 0; fid = 0;
inserted = 0; inserted = 0;
fullname = NULL; fullname = NULL;
fnp = fidp = namep = NULL; fnp = namep = NULL;
/* Check the arguments. */ /* Check the arguments. */
if (type != DB_BTREE && type != DB_HASH && type != DB_RECNO) { 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. */ /* Get the log file id. */
if ((ret = __db_appname(dblp->dbenv, 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); return (ret);
LOCK_LOGREGION(dblp); LOCK_LOGREGION(dblp);
@ -70,8 +69,7 @@ log_register(dblp, dbp, name, type, idp)
fnp != NULL; fnp = SH_TAILQ_NEXT(fnp, q, __fname)) { fnp != NULL; fnp = SH_TAILQ_NEXT(fnp, q, __fname)) {
if (fid <= fnp->id) if (fid <= fnp->id)
fid = fnp->id + 1; fid = fnp->id + 1;
if (!memcmp(dbp->lock.fileid, if (!memcmp(dbp->lock.fileid, fnp->ufid, DB_FILE_ID_LEN)) {
R_ADDR(dblp, fnp->fileid_off), DB_FILE_ID_LEN)) {
++fnp->ref; ++fnp->ref;
fid = fnp->id; fid = fnp->id;
goto found; goto found;
@ -84,15 +82,7 @@ log_register(dblp, dbp, name, type, idp)
fnp->ref = 1; fnp->ref = 1;
fnp->id = fid; fnp->id = fid;
fnp->s_type = type; fnp->s_type = type;
memcpy(fnp->ufid, dbp->lock.fileid, DB_FILE_ID_LEN);
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);
len = strlen(name) + 1; len = strlen(name) + 1;
if ((ret = __db_shalloc(dblp->addr, len, 0, &namep)) != 0) if ((ret = __db_shalloc(dblp->addr, len, 0, &namep)) != 0)
@ -126,8 +116,6 @@ err: /*
SH_TAILQ_REMOVE(&dblp->lp->fq, fnp, q, __fname); SH_TAILQ_REMOVE(&dblp->lp->fq, fnp, q, __fname);
if (namep != NULL) if (namep != NULL)
__db_shalloc_free(dblp->addr, namep); __db_shalloc_free(dblp->addr, namep);
if (fidp != NULL)
__db_shalloc_free(dblp->addr, fidp);
if (fnp != NULL) if (fnp != NULL)
__db_shalloc_free(dblp->addr, fnp); __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.data = R_ADDR(dblp, fnp->name_off);
r_name.size = strlen(r_name.data) + 1; r_name.size = strlen(r_name.data) + 1;
memset(&fid_dbt, 0, sizeof(fid_dbt)); 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; fid_dbt.size = DB_FILE_ID_LEN;
if ((ret = __log_register_log(dblp, NULL, &r_unused, if ((ret = __log_register_log(dblp, NULL, &r_unused,
0, LOG_CLOSE, &r_name, &fid_dbt, fid, fnp->s_type)) != 0) 0, LOG_CLOSE, &r_name, &fid_dbt, fid, fnp->s_type)) != 0)
@ -190,7 +178,6 @@ log_unregister(dblp, fid)
if (fnp->ref > 1) if (fnp->ref > 1)
--fnp->ref; --fnp->ref;
else { else {
__db_shalloc_free(dblp->addr, R_ADDR(dblp, fnp->fileid_off));
__db_shalloc_free(dblp->addr, R_ADDR(dblp, fnp->name_off)); __db_shalloc_free(dblp->addr, R_ADDR(dblp, fnp->name_off));
SH_TAILQ_REMOVE(&dblp->lp->fq, fnp, q, __fname); SH_TAILQ_REMOVE(&dblp->lp->fq, fnp, q, __fname);
__db_shalloc_free(dblp->addr, fnp); __db_shalloc_free(dblp->addr, fnp);

Some files were not shown because too many files have changed in this diff Show More