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>
* 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 \
db_shash db_thread hash hash_auto hash_conv hash_debug \
hash_dup hash_func hash_page hash_rec hash_stat lock \
lock_conflict lock_deadlock lock_util log log_archive \
lock_conflict lock_deadlock lock_region lock_util log log_archive \
log_auto log_compare log_findckp log_get log_put log_rec \
log_register mp_bh mp_fget mp_fopen mp_fput mp_fset \
mp_open mp_pr mp_region mp_sync mutex txn txn_auto \

View File

@ -1,7 +1,7 @@
/*-
* See the file LICENSE for redistribution information.
*
* Copyright (c) 1996, 1997
* Copyright (c) 1996, 1997, 1998
* Sleepycat Software. All rights reserved.
*/
/*
@ -47,18 +47,13 @@
#include "config.h"
#ifndef lint
static const char sccsid[] = "@(#)bt_close.c 10.25 (Sleepycat) 1/6/98";
static const char sccsid[] = "@(#)bt_close.c 10.32 (Sleepycat) 5/6/98";
#endif /* not lint */
#ifndef NO_SYSTEM_INCLUDES
#include <sys/types.h>
#include <sys/mman.h>
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#endif
#include "db_int.h"
@ -104,12 +99,12 @@ __bam_close(dbp)
* __bam_sync --
* Sync the btree to disk.
*
* PUBLIC: int __bam_sync __P((DB *, int));
* PUBLIC: int __bam_sync __P((DB *, u_int32_t));
*/
int
__bam_sync(argdbp, flags)
DB *argdbp;
int flags;
u_int32_t flags;
{
DB *dbp;
int ret;
@ -146,7 +141,7 @@ __bam_upstat(dbp)
BTMETA *meta;
DB_LOCK metalock;
db_pgno_t pgno;
int flags, ret;
u_int32_t flags;
/*
* We use a no-op log call to log the update of the statistics onto the
@ -166,8 +161,8 @@ __bam_upstat(dbp)
if (__bam_pget(dbp, (PAGE **)&meta, &pgno, 0) == 0) {
/* Log the change. */
if (DB_LOGGING(dbp) &&
(ret = __db_noop_log(dbp->dbenv->lg_info, dbp->txn,
&LSN(meta), 0)) == 0)
__db_noop_log(dbp->dbenv->lg_info, dbp->txn, &LSN(meta), 0,
dbp->log_fileid, PGNO_METADATA, &LSN(meta)) != 0)
goto err;
/* Update the statistics. */

View File

@ -1,7 +1,7 @@
/*-
* See the file LICENSE for redistribution information.
*
* Copyright (c) 1996, 1997
* Copyright (c) 1996, 1997, 1998
* Sleepycat Software. All rights reserved.
*/
/*
@ -47,14 +47,12 @@
#include "config.h"
#ifndef lint
static const char sccsid[] = "@(#)bt_compare.c 10.4 (Sleepycat) 9/3/97";
static const char sccsid[] = "@(#)bt_compare.c 10.9 (Sleepycat) 5/6/98";
#endif /* not lint */
#ifndef NO_SYSTEM_INCLUDES
#include <sys/types.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#endif
@ -106,7 +104,6 @@ __bam_cmp(dbp, k1, e)
if (B_TYPE(bk->type) == B_OVERFLOW)
bo = (BOVERFLOW *)bk;
else {
memset(&k2, 0, sizeof(k2));
k2.data = bk->data;
k2.size = bk->len;
}
@ -115,7 +112,6 @@ __bam_cmp(dbp, k1, e)
if (B_TYPE(bi->type) == B_OVERFLOW)
bo = (BOVERFLOW *)(bi->data);
else {
memset(&k2, 0, sizeof(k2));
k2.data = bi->data;
k2.size = bi->len;
}
@ -139,10 +135,21 @@ __bam_cmp(dbp, k1, e)
* Otherwise, we need a contiguous record so we can hand it
* to the user's routine.
*/
memset(&k2, 0, sizeof(k2));
if (__db_goff(dbp, &k2, bo->tlen,
bo->pgno, &t->bt_rdata.data, &t->bt_rdata.ulen) != 0)
abort();
bo->pgno, &t->bt_rdata.data, &t->bt_rdata.ulen) != 0) {
(void)__db_panic(dbp);
return (0);
}
}
/*
* XXX
* Note, we have not cleared the k2 DBT in this path. This should
* be okay, because the user's comparison routine had better not be
* looking at any fields other than the data/size. We don't clear
* it because we go through this path a lot and it's expensive.
*/
return ((*t->bt_compare)(k1, &k2));
}

View File

@ -1,14 +1,14 @@
/*-
* See the file LICENSE for redistribution information.
*
* Copyright (c) 1996, 1997
* Copyright (c) 1996, 1997, 1998
* Sleepycat Software. All rights reserved.
*/
#include "config.h"
#ifndef lint
static const char sccsid[] = "@(#)bt_conv.c 10.5 (Sleepycat) 9/15/97";
static const char sccsid[] = "@(#)bt_conv.c 10.6 (Sleepycat) 4/10/98";
#endif /* not lint */
#ifndef NO_SYSTEM_INCLUDES

View File

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

View File

@ -1,7 +1,7 @@
/*-
* See the file LICENSE for redistribution information.
*
* Copyright (c) 1996, 1997
* Copyright (c) 1996, 1997, 1998
* Sleepycat Software. All rights reserved.
*/
/*
@ -47,13 +47,12 @@
#include "config.h"
#ifndef lint
static const char sccsid[] = "@(#)bt_delete.c 10.25 (Sleepycat) 1/8/98";
static const char sccsid[] = "@(#)bt_delete.c 10.31 (Sleepycat) 5/6/98";
#endif /* not lint */
#ifndef NO_SYSTEM_INCLUDES
#include <sys/types.h>
#include <stdio.h>
#include <string.h>
#endif
@ -67,14 +66,14 @@ static int __bam_dpages __P((DB *, BTREE *));
* __bam_delete --
* Delete the items referenced by a key.
*
* PUBLIC: int __bam_delete __P((DB *, DB_TXN *, DBT *, int));
* PUBLIC: int __bam_delete __P((DB *, DB_TXN *, DBT *, u_int32_t));
*/
int
__bam_delete(argdbp, txn, key, flags)
DB *argdbp;
DB_TXN *txn;
DBT *key;
int flags;
u_int32_t flags;
{
BTREE *t;
DB *dbp;
@ -87,8 +86,8 @@ __bam_delete(argdbp, txn, key, flags)
stack = 0;
/* Check for invalid flags. */
if ((ret =
__db_delchk(argdbp, flags, F_ISSET(argdbp, DB_AM_RDONLY))) != 0)
if ((ret = __db_delchk(argdbp,
key, flags, F_ISSET(argdbp, DB_AM_RDONLY))) != 0)
return (ret);
GETHANDLE(argdbp, txn, &dbp, ret);
@ -107,6 +106,11 @@ __bam_delete(argdbp, txn, key, flags)
break;
for (; cnt > 0; --cnt, ++t->lstat.bt_deleted)
if (__bam_ca_delete(dbp, h->pgno, indx, NULL, 1) == 0) {
/*
* XXX
* Delete the key item first, otherwise the duplicate
* checks in __bam_ditem() won't work!
*/
if ((ret = __bam_ditem(dbp, h, indx)) != 0)
goto err;
if ((ret = __bam_ditem(dbp, h, indx)) != 0)
@ -138,14 +142,14 @@ err: if (stack)
* __ram_delete --
* Delete the items referenced by a key.
*
* PUBLIC: int __ram_delete __P((DB *, DB_TXN *, DBT *, int));
* PUBLIC: int __ram_delete __P((DB *, DB_TXN *, DBT *, u_int32_t));
*/
int
__ram_delete(argdbp, txn, key, flags)
DB *argdbp;
DB_TXN *txn;
DBT *key;
int flags;
u_int32_t flags;
{
BKEYDATA bk;
BTREE *t;
@ -159,8 +163,8 @@ __ram_delete(argdbp, txn, key, flags)
stack = 0;
/* Check for invalid flags. */
if ((ret =
__db_delchk(argdbp, flags, F_ISSET(argdbp, DB_AM_RDONLY))) != 0)
if ((ret = __db_delchk(argdbp,
key, flags, F_ISSET(argdbp, DB_AM_RDONLY))) != 0)
return (ret);
GETHANDLE(argdbp, txn, &dbp, ret);
@ -284,19 +288,32 @@ __bam_ditem(dbp, h, indx)
case P_LBTREE:
/*
* If it's a duplicate key, discard the index and don't touch
* the actual page item. This works because no data item can
* have an index that matches any other index so even if the
* data item is in an index "slot", it won't match any other
* index.
* the actual page item.
*
* XXX
* This works because no data item can have an index matching
* any other index so even if the data item is in a key "slot",
* it won't match any other index.
*/
if ((indx % 2) == 0) {
/*
* Check for a duplicate after us on the page. NOTE:
* we have to delete the key item before deleting the
* data item, otherwise the "indx + P_INDX" calculation
* won't work!
*/
if (!(indx % 2)) {
if (indx > 0 && h->inp[indx] == h->inp[indx - P_INDX])
return (__bam_adjindx(dbp,
h, indx, indx - P_INDX, 0));
if (indx + P_INDX < (u_int32_t)NUM_ENT(h) &&
h->inp[indx] == h->inp[indx + P_INDX])
return (__bam_adjindx(dbp,
h, indx, indx + O_INDX, 0));
/*
* Check for a duplicate before us on the page. It
* doesn't matter if we delete the key item before or
* after the data item for the purposes of this one.
*/
if (indx > 0 && h->inp[indx] == h->inp[indx - P_INDX])
return (__bam_adjindx(dbp,
h, indx, indx - P_INDX, 0));
}
/* FALLTHROUGH */
case P_LRECNO:
@ -396,7 +413,8 @@ __bam_dpage(dbp, key)
DB_LOCK lock;
PAGE *h;
db_pgno_t pgno;
int exact, level, ret;
int level; /* !!!: has to hold number of tree levels. */
int exact, ret;
ret = 0;
t = dbp->internal;
@ -527,13 +545,14 @@ __bam_dpages(dbp, t)
goto release;
/*
* If we deleted the next-to-last item from the root page, the tree
* can collapse a level. Try and write lock the remaining root + 1
* page and copy it onto the root page. If we can't get the lock,
* that's okay, the tree just stays a level deeper than we'd like.
* If we just deleted the last or next-to-last item from the root page,
* the tree can collapse a level. Write lock the last page referenced
* by the root page and copy it over the root page. If we can't get a
* write lock, that's okay, the tree just remains a level deeper than
* we'd like.
*/
h = epg->page;
if (h->pgno == PGNO_ROOT && NUM_ENT(h) == 1) {
if (h->pgno == PGNO_ROOT && NUM_ENT(h) <= 1) {
pgno = TYPE(epg->page) == P_IBTREE ?
GET_BINTERNAL(epg->page, 0)->pgno :
GET_RINTERNAL(epg->page, 0)->pgno;
@ -573,13 +592,21 @@ __bam_dpages(dbp, t)
(void)memp_fset(dbp->mpf, epg->page, DB_MPOOL_DIRTY);
/*
* Free the last page in that level of the btree and discard
* the lock. (The call to __bam_free discards our reference
* Free the page copied onto the root page and discard its
* lock. (The call to __bam_free() discards our reference
* to the page.)
*
* It's possible that the reverse split we're doing involves
* pages from the stack of pages we're deleting. Don't free
* the page twice.
*/
if (h->pgno == (epg + 1)->page->pgno)
(void)memp_fput(dbp->mpf, h, 0);
else {
(void)__bam_free(dbp, h);
(void)__BT_TLPUT(dbp, lock);
++t->lstat.bt_freed;
}
(void)__BT_TLPUT(dbp, lock);
/* Adjust the cursors. */
__bam_ca_move(dbp, h->pgno, PGNO_ROOT);
@ -596,12 +623,17 @@ __bam_dpages(dbp, t)
* Don't bother checking for errors. We've unlinked the subtree from
* the tree, and there's no possibility of recovery.
*/
for (; ++epg <= t->bt_csp; ++t->lstat.bt_freed) {
while (++epg <= t->bt_csp) {
/*
* XXX
* Why do we need to do this? Isn't the page already empty?
*/
if (NUM_ENT(epg->page) != 0)
(void)__bam_ditem(dbp, epg->page, epg->indx);
(void)__bam_free(dbp, epg->page);
(void)__BT_TLPUT(dbp, epg->lock);
++t->lstat.bt_freed;
}
return (0);

View File

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

View File

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

View File

@ -1,7 +1,7 @@
/*-
* See the file LICENSE for redistribution information.
*
* Copyright (c) 1996, 1997
* Copyright (c) 1996, 1997, 1998
* Sleepycat Software. All rights reserved.
*/
/*
@ -47,15 +47,13 @@
#include "config.h"
#ifndef lint
static const char sccsid[] = "@(#)bt_put.c 10.38 (Sleepycat) 1/8/98";
static const char sccsid[] = "@(#)bt_put.c 10.45 (Sleepycat) 5/25/98";
#endif /* not lint */
#ifndef NO_SYSTEM_INCLUDES
#include <sys/types.h>
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#endif
@ -75,21 +73,22 @@ static u_int32_t __bam_partsize __P((DBT *, PAGE *, u_int32_t));
* __bam_put --
* Add a new key/data pair or replace an existing pair (btree).
*
* PUBLIC: int __bam_put __P((DB *, DB_TXN *, DBT *, DBT *, int));
* PUBLIC: int __bam_put __P((DB *, DB_TXN *, DBT *, DBT *, u_int32_t));
*/
int
__bam_put(argdbp, txn, key, data, flags)
DB *argdbp;
DB_TXN *txn;
DBT *key, *data;
int flags;
u_int32_t flags;
{
BTREE *t;
CURSOR c;
DB *dbp;
PAGE *h;
db_indx_t indx;
int exact, iflags, isdeleted, newkey, replace, ret, stack;
u_int32_t iitem_flags, insert_flags;
int exact, isdeleted, newkey, ret, stack;
DEBUG_LWRITE(argdbp, txn, "bam_put", key, data, flags);
@ -121,14 +120,13 @@ retry: /*
* been marked for deletion, we do a replace, otherwise, it has to be
* a set of duplicates, and we simply append a new one to the set.
*/
isdeleted = replace = 0;
isdeleted = 0;
if (exact) {
if ((ret = __bam_isdeleted(dbp, h, indx, &isdeleted)) != 0)
goto err;
if (isdeleted) {
replace = 1;
if (isdeleted)
__bam_ca_replace(dbp, h->pgno, indx, REPLACE_SETUP);
} else
else
if (flags == DB_NOOVERWRITE) {
ret = DB_KEYEXIST;
goto err;
@ -179,42 +177,38 @@ retry: /*
t->bt_csp->page = h = c.page;
indx = c.dindx;
}
iflags = DB_AFTER;
insert_flags = DB_AFTER;
} else
iflags = DB_CURRENT;
insert_flags = DB_CURRENT;
} else
iflags = DB_BEFORE;
insert_flags = DB_BEFORE;
/*
* The pages we're using may be modified by __bam_iitem(), so make
* sure we reset the stack.
*/
ret = __bam_iitem(dbp,
&h, &indx, key, data, iflags, newkey ? BI_NEWKEY : 0);
iitem_flags = 0;
if (newkey)
iitem_flags |= BI_NEWKEY;
if (isdeleted)
iitem_flags |= BI_DOINCR;
ret = __bam_iitem(dbp, &h, &indx, key, data, insert_flags, iitem_flags);
t->bt_csp->page = h;
t->bt_csp->indx = indx;
switch (ret) {
case 0:
/*
* Done. Clean up the cursor, and, if we're doing record
* numbers, adjust the internal page counts.
*/
if (replace)
/* Done. Clean up the cursor. */
if (isdeleted)
__bam_ca_replace(dbp, h->pgno, indx, REPLACE_SUCCESS);
if (!replace && F_ISSET(dbp, DB_BT_RECNUM))
ret = __bam_adjust(dbp, t, 1);
break;
case DB_NEEDSPLIT:
/*
* We have to split the page. Back out the cursor setup,
* discard the stack of pages, and do the split.
*/
if (replace) {
replace = 0;
if (isdeleted)
__bam_ca_replace(dbp, h->pgno, indx, REPLACE_FAILED);
}
(void)__bam_stkrel(dbp);
stack = 0;
@ -225,7 +219,7 @@ retry: /*
goto retry;
/* NOTREACHED */
default:
if (replace)
if (isdeleted)
__bam_ca_replace(dbp, h->pgno, indx, REPLACE_FAILED);
break;
}
@ -393,7 +387,8 @@ __bam_lookup(dbp, key, exactp)
for (indx = 0;
indx < (db_indx_t)(NUM_ENT(h) - P_INDX) &&
h->inp[indx] == h->inp[indx + P_INDX];
indx += P_INDX);
indx += P_INDX)
;
e.indx = indx;
}
goto fast;
@ -427,7 +422,7 @@ slow: return (__bam_search(dbp, key, S_INSERT, 1, NULL, exactp));
* Insert an item into the tree.
*
* PUBLIC: int __bam_iitem __P((DB *,
* PUBLIC: PAGE **, db_indx_t *, DBT *, DBT *, int, int));
* PUBLIC: PAGE **, db_indx_t *, DBT *, DBT *, u_int32_t, u_int32_t));
*/
int
__bam_iitem(dbp, hp, indxp, key, data, op, flags)
@ -435,13 +430,13 @@ __bam_iitem(dbp, hp, indxp, key, data, op, flags)
PAGE **hp;
db_indx_t *indxp;
DBT *key, *data;
int op, flags;
u_int32_t op, flags;
{
BTREE *t;
BKEYDATA *bk;
DBT tdbt;
PAGE *h;
db_indx_t indx;
db_indx_t indx, nbytes;
u_int32_t data_size, have_bytes, need_bytes, needed;
int bigkey, bigdata, dupadjust, replace, ret;
@ -466,12 +461,27 @@ __bam_iitem(dbp, hp, indxp, key, data, op, flags)
++*indxp;
/* Remove the current item if it's a DB_CURRENT op. */
if (op == DB_CURRENT && (ret = __db_ditem(dbp, *hp, *indxp,
BKEYDATA_SIZE(GET_BKEYDATA(*hp, *indxp)->len))) != 0)
if (op == DB_CURRENT) {
bk = GET_BKEYDATA(*hp, *indxp);
switch (B_TYPE(bk->type)) {
case B_KEYDATA:
nbytes = BKEYDATA_SIZE(bk->len);
break;
case B_OVERFLOW:
nbytes = BOVERFLOW_SIZE;
break;
default:
return (__db_pgfmt(dbp, h->pgno));
}
if ((ret = __db_ditem(dbp, *hp, *indxp, nbytes)) != 0)
return (ret);
}
/* Put the new/replacement item onto the page. */
return (__db_dput(dbp, data, hp, indxp, __bam_new));
if ((ret = __db_dput(dbp, data, hp, indxp, __bam_new)) != 0)
return (ret);
goto done;
}
/* Handle fixed-length records: build the real record. */
@ -568,7 +578,7 @@ __bam_iitem(dbp, hp, indxp, key, data, op, flags)
case DB_BEFORE: /* 2. Insert a new key/data pair. */
break;
default:
abort();
return (EINVAL);
}
/* Add the key. */
@ -638,7 +648,7 @@ __bam_iitem(dbp, hp, indxp, key, data, op, flags)
replace = 1;
break;
default:
abort();
return (EINVAL);
}
}
@ -666,9 +676,8 @@ __bam_iitem(dbp, hp, indxp, key, data, op, flags)
return (ret);
}
++t->lstat.bt_added;
ret = memp_fset(dbp->mpf, h, DB_MPOOL_DIRTY);
if ((ret = memp_fset(dbp->mpf, h, DB_MPOOL_DIRTY)) != 0)
return (ret);
/*
* If the page is at least 50% full, and we added a duplicate, see if
@ -681,9 +690,25 @@ __bam_iitem(dbp, hp, indxp, key, data, op, flags)
return (ret);
}
/*
* If we've changed the record count, update the tree. Record counts
* need to be updated in recno databases and in btree databases where
* we are supporting records. In both cases, adjust the count if the
* operation wasn't performed on the current record or when the caller
* overrides and wants the adjustment made regardless.
*/
done: if (LF_ISSET(BI_DOINCR) ||
(op != DB_CURRENT &&
(F_ISSET(dbp, DB_BT_RECNUM) || dbp->type == DB_RECNO)))
if ((ret = __bam_adjust(dbp, t, 1)) != 0)
return (ret);
/* If we've modified a recno file, set the flag */
if (t->bt_recno != NULL)
F_SET(t->bt_recno, RECNO_MODIFIED);
++t->lstat.bt_added;
return (ret);
}
@ -1036,8 +1061,8 @@ __bam_partial(dbp, dbt, h, indx, nbytes)
BOVERFLOW *bo;
DBT copy;
u_int32_t len, tlen;
int ret;
u_int8_t *p;
int ret;
COMPQUIET(bo, NULL);
@ -1065,59 +1090,62 @@ __bam_partial(dbp, dbt, h, indx, nbytes)
bk->len = 0;
}
/* We use nul bytes for extending the record, get it over with. */
/*
* We use nul bytes for any part of the record that isn't specified,
* get it over with.
*/
memset(t->bt_rdata.data, 0, nbytes);
tlen = 0;
if (B_TYPE(bk->type) == B_OVERFLOW) {
/* Take up to doff bytes from the record. */
/*
* In the case of an overflow record, we shift things around
* in the current record rather than allocate a separate copy.
*/
memset(&copy, 0, sizeof(copy));
if ((ret = __db_goff(dbp, &copy, bo->tlen,
bo->pgno, &t->bt_rdata.data, &t->bt_rdata.ulen)) != 0)
return (ret);
tlen += dbt->doff;
/* Skip any leading data from the original record. */
tlen = dbt->doff;
p = (u_int8_t *)t->bt_rdata.data + dbt->doff;
/*
* If the original record was larger than the offset:
* If dlen > size, shift the remaining data down.
* If dlen < size, shift the remaining data up.
* Copy in any trailing data from the original record.
*
* If the original record was larger than the original offset
* plus the bytes being deleted, there is trailing data in the
* original record we need to preserve. If we aren't deleting
* the same number of bytes as we're inserting, copy it up or
* down, into place.
*
* Use memmove(), the regions may overlap.
*/
p = t->bt_rdata.data;
if (bo->tlen > dbt->doff)
if (dbt->dlen > dbt->size) {
tlen += len = bo->tlen -
dbt->doff - (dbt->dlen - dbt->size);
memmove(p + dbt->doff + dbt->size,
p + dbt->doff + dbt->dlen, len);
} else if (dbt->dlen < dbt->size) {
tlen += len = bo->tlen -
dbt->doff - (dbt->size - dbt->dlen);
memmove(p + dbt->doff + dbt->dlen,
p + dbt->doff + dbt->size, len);
} else
tlen += bo->tlen - dbt->doff;
if (bo->tlen > dbt->doff + dbt->dlen) {
len = bo->tlen - (dbt->doff + dbt->dlen);
if (dbt->dlen != dbt->size)
memmove(p + dbt->size, p + dbt->dlen, len);
tlen += len;
}
/* Copy in the user's data. */
memcpy((u_int8_t *)t->bt_rdata.data + dbt->doff,
dbt->data, dbt->size);
/* Copy in the application provided data. */
memcpy(p, dbt->data, dbt->size);
tlen += dbt->size;
} else {
/* Take up to doff bytes from the record. */
/* Copy in any leading data from the original record. */
memcpy(t->bt_rdata.data,
bk->data, dbt->doff > bk->len ? bk->len : dbt->doff);
tlen += dbt->doff;
tlen = dbt->doff;
p = (u_int8_t *)t->bt_rdata.data + dbt->doff;
/* Copy in the user's data. */
memcpy((u_int8_t *)t->bt_rdata.data +
dbt->doff, dbt->data, dbt->size);
/* Copy in the application provided data. */
memcpy(p, dbt->data, dbt->size);
tlen += dbt->size;
/* Copy in any remaining data. */
/* Copy in any trailing data from the original record. */
len = dbt->doff + dbt->dlen;
if (bk->len > len) {
memcpy((u_int8_t *)t->bt_rdata.data + dbt->doff +
dbt->size, bk->data + len, bk->len - len);
memcpy(p + dbt->size, bk->data + len, bk->len - len);
tlen += bk->len - len;
}
}

View File

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

View File

@ -1,14 +1,14 @@
/*-
* See the file LICENSE for redistribution information.
*
* Copyright (c) 1997
* Copyright (c) 1997, 1998
* Sleepycat Software. All rights reserved.
*/
#include "config.h"
#ifndef lint
static const char sccsid[] = "@(#)bt_recno.c 10.26 (Sleepycat) 1/8/98";
static const char sccsid[] = "@(#)bt_recno.c 10.37 (Sleepycat) 5/23/98";
#endif /* not lint */
#ifndef NO_SYSTEM_INCLUDES
@ -16,8 +16,6 @@ static const char sccsid[] = "@(#)bt_recno.c 10.26 (Sleepycat) 1/8/98";
#include <errno.h>
#include <limits.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#endif
@ -25,16 +23,17 @@ static const char sccsid[] = "@(#)bt_recno.c 10.26 (Sleepycat) 1/8/98";
#include "db_page.h"
#include "btree.h"
static int __ram_add __P((DB *, db_recno_t *, DBT *, int, int));
static int __ram_add __P((DB *, db_recno_t *, DBT *, u_int32_t, u_int32_t));
static int __ram_c_close __P((DBC *));
static int __ram_c_del __P((DBC *, int));
static int __ram_c_get __P((DBC *, DBT *, DBT *, int));
static int __ram_c_put __P((DBC *, DBT *, DBT *, int));
static int __ram_c_del __P((DBC *, u_int32_t));
static int __ram_c_get __P((DBC *, DBT *, DBT *, u_int32_t));
static int __ram_c_put __P((DBC *, DBT *, DBT *, u_int32_t));
static int __ram_fmap __P((DB *, db_recno_t));
static int __ram_get __P((DB *, DB_TXN *, DBT *, DBT *, int));
static int __ram_put __P((DB *, DB_TXN *, DBT *, DBT *, int));
static int __ram_get __P((DB *, DB_TXN *, DBT *, DBT *, u_int32_t));
static int __ram_iget __P((DB *, DBT *, DBT *));
static int __ram_put __P((DB *, DB_TXN *, DBT *, DBT *, u_int32_t));
static int __ram_source __P((DB *, RECNO *, const char *));
static int __ram_sync __P((DB *, int));
static int __ram_sync __P((DB *, u_int32_t));
static int __ram_update __P((DB *, db_recno_t, int));
static int __ram_vmap __P((DB *, db_recno_t));
static int __ram_writeback __P((DB *));
@ -142,7 +141,7 @@ __ram_open(dbp, type, dbinfo)
err: /* If we mmap'd a source file, discard it. */
if (rp->re_smap != NULL)
(void)__db_unmap(rp->re_smap, rp->re_msize);
(void)__db_unmapfile(rp->re_smap, rp->re_msize);
/* If we opened a source file, discard it. */
if (rp->re_fd != -1)
@ -199,9 +198,9 @@ __ram_cursor(dbp, txn, dbcp)
* All cursors are queued from the master DB structure. Add the
* cursor to that queue.
*/
DB_THREAD_LOCK(dbp);
CURSOR_SETUP(dbp);
TAILQ_INSERT_HEAD(&dbp->curs_queue, dbc, links);
DB_THREAD_UNLOCK(dbp);
CURSOR_TEARDOWN(dbp);
*dbcp = dbc;
return (0);
@ -216,16 +215,10 @@ __ram_get(argdbp, txn, key, data, flags)
DB *argdbp;
DB_TXN *txn;
DBT *key, *data;
int flags;
u_int32_t flags;
{
BTREE *t;
DB *dbp;
PAGE *h;
db_indx_t indx;
db_recno_t recno;
int exact, ret, stack;
stack = 0;
int ret;
DEBUG_LWRITE(argdbp, txn, "ram_get", key, NULL, flags);
@ -234,6 +227,30 @@ __ram_get(argdbp, txn, key, data, flags)
return (ret);
GETHANDLE(argdbp, txn, &dbp, ret);
ret = __ram_iget(dbp, key, data);
PUTHANDLE(dbp);
return (ret);
}
/*
* __ram_iget --
* Internal ram get function, called for both standard and cursor
* get after the flags have been checked.
*/
static int
__ram_iget(dbp, key, data)
DB *dbp;
DBT *key, *data;
{
BTREE *t;
PAGE *h;
db_indx_t indx;
db_recno_t recno;
int exact, ret, stack;
stack = 0;
t = dbp->internal;
/* Check the user's record number and fill in as necessary. */
@ -265,7 +282,6 @@ done: /* Discard the stack. */
if (stack)
__bam_stkrel(dbp);
PUTHANDLE(dbp);
return (ret);
}
@ -278,7 +294,7 @@ __ram_put(argdbp, txn, key, data, flags)
DB *argdbp;
DB_TXN *txn;
DBT *key, *data;
int flags;
u_int32_t flags;
{
BTREE *t;
DB *dbp;
@ -324,7 +340,7 @@ __ram_put(argdbp, txn, key, data, flags)
static int
__ram_sync(argdbp, flags)
DB *argdbp;
int flags;
u_int32_t flags;
{
DB *dbp;
int ret;
@ -361,7 +377,7 @@ __ram_close(argdbp)
/* Close any underlying mmap region. */
if (rp->re_smap != NULL)
(void)__db_unmap(rp->re_smap, rp->re_msize);
(void)__db_unmapfile(rp->re_smap, rp->re_msize);
/* Close any backing source file descriptor. */
if (rp->re_fd != -1)
@ -403,17 +419,10 @@ __ram_c_iclose(dbp, dbc)
DB *dbp;
DBC *dbc;
{
/*
* All cursors are queued from the master DB structure. For
* now, discard the DB handle which triggered this call, and
* replace it with the cursor's reference.
*/
dbp = dbc->dbp;
/* Remove the cursor from the queue. */
DB_THREAD_LOCK(dbp);
CURSOR_SETUP(dbp);
TAILQ_REMOVE(&dbp->curs_queue, dbc, links);
DB_THREAD_UNLOCK(dbp);
CURSOR_TEARDOWN(dbp);
/* Discard the structures. */
FREE(dbc->internal, sizeof(RCURSOR));
@ -429,7 +438,7 @@ __ram_c_iclose(dbp, dbc)
static int
__ram_c_del(dbc, flags)
DBC *dbc;
int flags;
u_int32_t flags;
{
DBT key;
RCURSOR *cp;
@ -466,7 +475,7 @@ static int
__ram_c_get(dbc, key, data, flags)
DBC *dbc;
DBT *key, *data;
int flags;
u_int32_t flags;
{
BTREE *t;
DB *dbp;
@ -537,7 +546,7 @@ retry: /* Update the record number. */
/*
* Return the key if the user didn't give us one, and then pass it
* into __ram_get().
* into __ram_iget().
*/
if (flags != DB_SET && flags != DB_SET_RANGE &&
(ret = __db_retcopy(key, &cp->recno, sizeof(cp->recno),
@ -555,7 +564,7 @@ retry: /* Update the record number. */
*
* Skip any keys that don't really exist.
*/
if ((ret = __ram_get(dbp, dbc->txn, key, data, 0)) != 0)
if ((ret = __ram_iget(dbp, key, data)) != 0)
if (ret == DB_KEYEMPTY &&
(flags == DB_NEXT || flags == DB_PREV))
goto retry;
@ -575,7 +584,7 @@ static int
__ram_c_put(dbc, key, data, flags)
DBC *dbc;
DBT *key, *data;
int flags;
u_int32_t flags;
{
BTREE *t;
RCURSOR *cp, copy;
@ -624,11 +633,6 @@ split: arg = &cp->recno;
if ((ret = __bam_stkrel(dbp)) != 0)
goto err;
if (flags != DB_CURRENT) {
/* Adjust the counts. */
if ((ret = __bam_adjust(dbp, t, 1)) != 0)
goto err;
switch (flags) {
case DB_AFTER:
/* Adjust the cursors. */
@ -646,8 +650,6 @@ split: arg = &cp->recno;
break;
}
}
/*
* The cursor was reset, so the delete adjustment is no
* longer necessary.
@ -679,7 +681,7 @@ __ram_ca(dbp, recno, op)
/*
* Adjust the cursors. See the comment in __bam_ca_delete().
*/
DB_THREAD_LOCK(dbp);
CURSOR_SETUP(dbp);
for (dbc = TAILQ_FIRST(&dbp->curs_queue);
dbc != NULL; dbc = TAILQ_NEXT(dbc, links)) {
cp = (RCURSOR *)dbc->internal;
@ -698,7 +700,7 @@ __ram_ca(dbp, recno, op)
break;
}
}
DB_THREAD_UNLOCK(dbp);
CURSOR_TEARDOWN(dbp);
}
#ifdef DEBUG
@ -715,14 +717,15 @@ __ram_cprint(dbp)
DBC *dbc;
RCURSOR *cp;
DB_THREAD_LOCK(dbp);
CURSOR_SETUP(dbp);
for (dbc = TAILQ_FIRST(&dbp->curs_queue);
dbc != NULL; dbc = TAILQ_NEXT(dbc, links)) {
cp = (RCURSOR *)dbc->internal;
fprintf(stderr,
"%#0x: recno: %lu\n", (u_int)cp, (u_long)cp->recno);
}
DB_THREAD_UNLOCK(dbp);
CURSOR_TEARDOWN(dbp);
return (0);
}
#endif /* DEBUG */
@ -853,11 +856,11 @@ __ram_source(dbp, rp, fname)
const char *fname;
{
size_t size;
u_int32_t mbytes, bytes;
int oflags, ret;
u_int32_t bytes, mbytes, oflags;
int ret;
if ((ret = __db_appname(dbp->dbenv,
DB_APP_DATA, NULL, fname, NULL, &rp->re_source)) != 0)
DB_APP_DATA, NULL, fname, 0, NULL, &rp->re_source)) != 0)
return (ret);
oflags = F_ISSET(dbp, DB_AM_RDONLY) ? DB_RDONLY : 0;
@ -886,7 +889,8 @@ __ram_source(dbp, rp, fname)
}
size = mbytes * MEGABYTE + bytes;
if ((ret = __db_map(rp->re_fd, (size_t)size, 1, 1, &rp->re_smap)) != 0)
if ((ret = __db_mapfile(rp->re_source,
rp->re_fd, (size_t)size, 1, &rp->re_smap)) != 0)
goto err;
rp->re_cmap = rp->re_smap;
rp->re_emap = (u_int8_t *)rp->re_smap + (rp->re_msize = size);
@ -952,7 +956,7 @@ __ram_writeback(dbp)
* open will fail.
*/
if (rp->re_smap != NULL) {
(void)__db_unmap(rp->re_smap, rp->re_msize);
(void)__db_unmapfile(rp->re_smap, rp->re_msize);
rp->re_smap = NULL;
}
@ -1078,19 +1082,22 @@ __ram_fmap(dbp, top)
sp = (u_int8_t *)rp->re_cmap;
ep = (u_int8_t *)rp->re_emap;
while (recno <= top) {
while (recno < top) {
if (sp >= ep) {
F_SET(rp, RECNO_EOF);
return (DB_NOTFOUND);
}
len = rp->re_len;
for (p = t->bt_rdata.data;
sp < ep && len > 0; *p++ = *sp++, --len);
sp < ep && len > 0; *p++ = *sp++, --len)
;
/*
* Another process may have read some portion of the input
* file already, in which case we just want to discard the
* new record.
* Another process may have read this record from the input
* file and stored it into the database already, in which
* case we don't need to repeat that operation. We detect
* this by checking if the last record we've read is greater
* or equal to the number of records in the database.
*
* XXX
* We should just do a seek, since the records are fixed
@ -1138,17 +1145,20 @@ __ram_vmap(dbp, top)
sp = (u_int8_t *)rp->re_cmap;
ep = (u_int8_t *)rp->re_emap;
while (recno <= top) {
while (recno < top) {
if (sp >= ep) {
F_SET(rp, RECNO_EOF);
return (DB_NOTFOUND);
}
for (data.data = sp; sp < ep && *sp != delim; ++sp);
for (data.data = sp; sp < ep && *sp != delim; ++sp)
;
/*
* Another process may have read some portion of the input
* file already, in which case we just want to discard the
* new record.
* Another process may have read this record from the input
* file and stored it into the database already, in which
* case we don't need to repeat that operation. We detect
* this by checking if the last record we've read is greater
* or equal to the number of records in the database.
*/
if (rp->re_last >= recno) {
data.size = sp - (u_int8_t *)data.data;
@ -1172,12 +1182,13 @@ __ram_add(dbp, recnop, data, flags, bi_flags)
DB *dbp;
db_recno_t *recnop;
DBT *data;
int flags, bi_flags;
u_int32_t flags, bi_flags;
{
BKEYDATA *bk;
BTREE *t;
PAGE *h;
db_indx_t indx;
int exact, ret, stack;
int exact, isdeleted, ret, stack;
t = dbp->internal;
@ -1190,34 +1201,63 @@ retry: /* Find the slot for insertion. */
stack = 1;
/*
* The recno access method doesn't currently support duplicates, so
* if an identical key is already in the tree we're either overwriting
* it or an error is returned.
* If DB_NOOVERWRITE is set and the item already exists in the tree,
* return an error unless the item has been marked for deletion.
*/
if (exact && LF_ISSET(DB_NOOVERWRITE)) {
isdeleted = 0;
if (exact) {
bk = GET_BKEYDATA(h, indx);
if (B_DISSET(bk->type)) {
isdeleted = 1;
__bam_ca_replace(dbp, h->pgno, indx, REPLACE_SETUP);
} else
if (LF_ISSET(DB_NOOVERWRITE)) {
ret = DB_KEYEXIST;
goto err;
}
}
/*
* Select the arguments for __bam_iitem() and do the insert. If the
* key is an exact match, or we're replacing the data item with a
* new data item. If the key isn't an exact match, we're inserting
* a new key/data pair, before the search location.
* new data item, replace the current item. If the key isn't an exact
* match, we're inserting a new key/data pair, before the search
* location.
*/
if ((ret = __bam_iitem(dbp, &h, &indx, NULL,
data, exact ? DB_CURRENT : DB_BEFORE, bi_flags)) == DB_NEEDSPLIT) {
switch (ret = __bam_iitem(dbp,
&h, &indx, NULL, data, exact ? DB_CURRENT : DB_BEFORE, bi_flags)) {
case 0:
/*
* Done. Clean up the cursor and adjust the internal page
* counts.
*/
if (isdeleted)
__bam_ca_replace(dbp, h->pgno, indx, REPLACE_SUCCESS);
break;
case DB_NEEDSPLIT:
/*
* We have to split the page. Back out the cursor setup,
* discard the stack of pages, and do the split.
*/
if (isdeleted)
__bam_ca_replace(dbp, h->pgno, indx, REPLACE_FAILED);
(void)__bam_stkrel(dbp);
stack = 0;
if ((ret = __bam_split(dbp, recnop)) != 0)
goto err;
goto retry;
}
if (!exact && ret == 0)
__bam_adjust(dbp, t, 1);
if ((ret = __bam_split(dbp, recnop)) != 0)
break;
goto retry;
/* NOTREACHED */
default:
if (isdeleted)
__bam_ca_replace(dbp, h->pgno, indx, REPLACE_FAILED);
break;
}
err: if (stack)
__bam_stkrel(dbp);
return (ret);
}

View File

@ -1,7 +1,7 @@
/*-
* See the file LICENSE for redistribution information.
*
* Copyright (c) 1996, 1997
* Copyright (c) 1996, 1997, 1998
* Sleepycat Software. All rights reserved.
*/
/*
@ -44,14 +44,11 @@
#include "config.h"
#ifndef lint
static const char sccsid[] = "@(#)bt_rsearch.c 10.8 (Sleepycat) 8/24/97";
static const char sccsid[] = "@(#)bt_rsearch.c 10.15 (Sleepycat) 5/6/98";
#endif /* not lint */
#ifndef NO_SYSTEM_INCLUDES
#include <sys/types.h>
#include <stdio.h>
#include <stdlib.h>
#endif
#include "db_int.h"
@ -62,13 +59,13 @@ static const char sccsid[] = "@(#)bt_rsearch.c 10.8 (Sleepycat) 8/24/97";
* __bam_rsearch --
* Search a btree for a record number.
*
* PUBLIC: int __bam_rsearch __P((DB *, db_recno_t *, u_int, int, int *));
* PUBLIC: int __bam_rsearch __P((DB *, db_recno_t *, u_int32_t, int, int *));
*/
int
__bam_rsearch(dbp, recnop, flags, stop, exactp)
DB *dbp;
db_recno_t *recnop;
u_int flags;
u_int32_t flags;
int stop, *exactp;
{
BINTERNAL *bi;
@ -78,7 +75,7 @@ __bam_rsearch(dbp, recnop, flags, stop, exactp)
RINTERNAL *ri;
db_indx_t indx, top;
db_pgno_t pg;
db_recno_t recno, total;
db_recno_t i, recno, total;
int isappend, ret, stack;
t = dbp->internal;
@ -136,8 +133,7 @@ __bam_rsearch(dbp, recnop, flags, stop, exactp)
*exactp = 1;
else {
*exactp = 0;
if (flags == S_DELETE ||
flags == S_FIND || recno > total + 1) {
if (!PAST_END_OK(flags) || recno > total + 1) {
(void)memp_fput(dbp->mpf, h, 0);
(void)__BT_LPUT(dbp, lock);
return (DB_NOTFOUND);
@ -164,30 +160,65 @@ __bam_rsearch(dbp, recnop, flags, stop, exactp)
stack = 1;
}
/* Records in the tree are 0-based, and record numbers are 1-based. */
--recno;
/*
* !!!
* Record numbers in the tree are 0-based, but the recno is
* 1-based. All of the calculations below have to take this
* into account.
*/
for (total = 0;;) {
switch (TYPE(h)) {
case P_LBTREE:
BT_STK_ENTER(t, h, (recno - total) * P_INDX, lock, ret);
recno -= total;
/*
* There may be logically deleted records on the page,
* walk the page correcting for them. The record may
* not exist if there are enough deleted records in the
* page.
*/
if (recno <= NUM_ENT(h))
for (i = recno - 1;; --i) {
if (B_DISSET(GET_BKEYDATA(h,
i * P_INDX + O_INDX)->type))
++recno;
if (i == 0)
break;
}
if (recno > NUM_ENT(h)) {
*exactp = 0;
if (!PAST_END_OK(flags) ||
recno > (db_recno_t)(NUM_ENT(h) + 1)) {
ret = DB_NOTFOUND;
goto err;
}
}
/* Correct from 1-based to 0-based for a page offset. */
--recno;
BT_STK_ENTER(t, h, recno * P_INDX, lock, ret);
return (ret);
case P_IBTREE:
for (indx = 0, top = NUM_ENT(h);;) {
bi = GET_BINTERNAL(h, indx);
if (++indx == top || total + bi->nrecs > recno)
if (++indx == top || total + bi->nrecs >= recno)
break;
total += bi->nrecs;
}
pg = bi->pgno;
break;
case P_LRECNO:
BT_STK_ENTER(t, h, recno - total, lock, ret);
recno -= total;
/* Correct from 1-based to 0-based for a page offset. */
--recno;
BT_STK_ENTER(t, h, recno, lock, ret);
return (ret);
case P_IRECNO:
for (indx = 0, top = NUM_ENT(h);;) {
ri = GET_RINTERNAL(h, indx);
if (++indx == top || total + ri->nrecs > recno)
if (++indx == top || total + ri->nrecs >= recno)
break;
total += ri->nrecs;
}
@ -244,13 +275,13 @@ err: BT_STK_POP(t);
* __bam_adjust --
* Adjust the tree after adding or deleting a record.
*
* PUBLIC: int __bam_adjust __P((DB *, BTREE *, int));
* PUBLIC: int __bam_adjust __P((DB *, BTREE *, int32_t));
*/
int
__bam_adjust(dbp, t, adjust)
DB *dbp;
BTREE *t;
int adjust;
int32_t adjust;
{
EPG *epg;
PAGE *h;
@ -264,7 +295,7 @@ __bam_adjust(dbp, t, adjust)
(ret = __bam_cadjust_log(dbp->dbenv->lg_info,
dbp->txn, &LSN(h), 0, dbp->log_fileid,
PGNO(h), &LSN(h), (u_int32_t)epg->indx,
(int32_t)adjust, 1)) != 0)
adjust, 1)) != 0)
return (ret);
if (TYPE(h) == P_IBTREE)
@ -322,26 +353,31 @@ db_recno_t
__bam_total(h)
PAGE *h;
{
db_recno_t recs;
db_indx_t nxt, top;
db_recno_t nrecs;
db_indx_t indx, top;
nrecs = 0;
top = NUM_ENT(h);
switch (TYPE(h)) {
case P_LBTREE:
recs = NUM_ENT(h) / 2;
/* Check for logically deleted records. */
for (indx = 0; indx < top; indx += P_INDX)
if (!B_DISSET(GET_BKEYDATA(h, indx + O_INDX)->type))
++nrecs;
break;
case P_IBTREE:
for (recs = 0, nxt = 0, top = NUM_ENT(h); nxt < top; ++nxt)
recs += GET_BINTERNAL(h, nxt)->nrecs;
for (indx = 0; indx < top; indx += O_INDX)
nrecs += GET_BINTERNAL(h, indx)->nrecs;
break;
case P_LRECNO:
recs = NUM_ENT(h);
nrecs = NUM_ENT(h);
break;
case P_IRECNO:
for (recs = 0, nxt = 0, top = NUM_ENT(h); nxt < top; ++nxt)
recs += GET_RINTERNAL(h, nxt)->nrecs;
for (indx = 0; indx < top; indx += O_INDX)
nrecs += GET_RINTERNAL(h, indx)->nrecs;
break;
default:
abort();
}
return (recs);
return (nrecs);
}

View File

@ -1,7 +1,7 @@
/*-
* See the file LICENSE for redistribution information.
*
* Copyright (c) 1996, 1997
* Copyright (c) 1996, 1997, 1998
* Sleepycat Software. All rights reserved.
*/
/*
@ -47,15 +47,13 @@
#include "config.h"
#ifndef lint
static const char sccsid[] = "@(#)bt_search.c 10.9 (Sleepycat) 11/18/97";
static const char sccsid[] = "@(#)bt_search.c 10.15 (Sleepycat) 5/6/98";
#endif /* not lint */
#ifndef NO_SYSTEM_INCLUDES
#include <sys/types.h>
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#endif
@ -68,13 +66,13 @@ static const char sccsid[] = "@(#)bt_search.c 10.9 (Sleepycat) 11/18/97";
* Search a btree for a key.
*
* PUBLIC: int __bam_search __P((DB *,
* PUBLIC: const DBT *, u_int, int, db_recno_t *, int *));
* PUBLIC: const DBT *, u_int32_t, int, db_recno_t *, int *));
*/
int
__bam_search(dbp, key, flags, stop, recnop, exactp)
DB *dbp;
const DBT *key;
u_int flags;
u_int32_t flags;
int stop, *exactp;
db_recno_t *recnop;
{
@ -109,8 +107,7 @@ __bam_search(dbp, key, flags, stop, recnop, exactp)
* Retrieve the root page.
*/
pg = PGNO_ROOT;
stack = F_ISSET(dbp, DB_BT_RECNUM) &&
(flags == S_INSERT || flags == S_DELETE);
stack = F_ISSET(dbp, DB_BT_RECNUM) && LF_ISSET(S_STACK);
if ((ret = __bam_lget(dbp,
0, pg, stack ? DB_LOCK_WRITE : DB_LOCK_READ, &lock)) != 0)
return (ret);
@ -179,6 +176,14 @@ __bam_search(dbp, key, flags, stop, recnop, exactp)
if (LF_ISSET(S_EXACT))
goto notfound;
/*
* !!!
* Possibly returning a deleted record -- DB_SET_RANGE,
* DB_KEYFIRST and DB_KEYLAST don't require an exact
* match, and we don't want to walk multiple pages here
* to find an undeleted record. This is handled in the
* __bam_c_search() routine.
*/
BT_STK_ENTER(t, h, base, lock, ret);
return (ret);
}
@ -249,7 +254,10 @@ match: *exactp = 1;
/*
* If we got here, we know that we have a btree leaf page.
*
* If there are duplicates, go to the first/last one.
* If there are duplicates, go to the first/last one. This is
* safe because we know that we're not going to leave the page,
* all duplicate sets that are not on overflow pages exist on a
* single leaf page.
*/
if (LF_ISSET(S_DUPLAST))
while (indx < (db_indx_t)(NUM_ENT(h) - P_INDX) &&
@ -261,8 +269,8 @@ match: *exactp = 1;
indx -= P_INDX;
/*
* Now check if we are allowed to return deleted item; if not
* find/last the first non-deleted item.
* Now check if we are allowed to return deleted items; if not
* find the next (or previous) non-deleted item.
*/
if (LF_ISSET(S_DELNO)) {
if (LF_ISSET(S_DUPLAST))

View File

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

View File

@ -1,21 +1,20 @@
/*-
* See the file LICENSE for redistribution information.
*
* Copyright (c) 1996, 1997
* Copyright (c) 1996, 1997, 1998
* Sleepycat Software. All rights reserved.
*/
#include "config.h"
#ifndef lint
static const char sccsid[] = "@(#)bt_stat.c 10.14 (Sleepycat) 10/25/97";
static const char sccsid[] = "@(#)bt_stat.c 10.17 (Sleepycat) 4/26/98";
#endif /* not lint */
#ifndef NO_SYSTEM_INCLUDES
#include <sys/types.h>
#include <errno.h>
#include <stdlib.h>
#include <string.h>
#endif
@ -29,14 +28,14 @@ static void __bam_add_rstat __P((DB_BTREE_LSTAT *, DB_BTREE_STAT *));
* __bam_stat --
* Gather/print the btree statistics
*
* PUBLIC: int __bam_stat __P((DB *, void *, void *(*)(size_t), int));
* PUBLIC: int __bam_stat __P((DB *, void *, void *(*)(size_t), u_int32_t));
*/
int
__bam_stat(argdbp, spp, db_malloc, flags)
DB *argdbp;
void *spp;
void *(*db_malloc) __P((size_t));
int flags;
u_int32_t flags;
{
BTMETA *meta;
BTREE *t;

View File

@ -1,16 +1,12 @@
/*-
* See the file LICENSE for redistribution information.
*
* Copyright (c) 1996, 1997
* Copyright (c) 1996, 1997, 1998
* Sleepycat Software. All rights reserved.
*
* @(#)btree.src 10.8 (Sleepycat) 4/10/98
*/
#include "config.h"
#ifndef lint
static const char sccsid[] = "@(#)btree.src 10.6 (Sleepycat) 11/2/97";
#endif /* not lint */
PREFIX bam
/*

View File

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

View File

@ -1,14 +1,14 @@
/*-
* See the file LICENSE for redistribution information.
*
* Copyright (c) 1996, 1997
* Copyright (c) 1996, 1997, 1998
* Sleepycat Software. All rights reserved.
*/
#include "config.h"
#ifndef lint
static const char sccsid[] = "@(#)getlong.c 10.2 (Sleepycat) 5/1/97";
static const char sccsid[] = "@(#)getlong.c 10.3 (Sleepycat) 4/10/98";
#endif /* not lint */
#ifndef NO_SYSTEM_INCLUDES

View File

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

View File

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

View File

@ -1,14 +1,14 @@
/*-
* See the file LICENSE for redistribution information.
*
* Copyright (c) 1996, 1997
* Copyright (c) 1996, 1997, 1998
* Sleepycat Software. All rights reserved.
*/
#include "config.h"
#ifndef lint
static const char sccsid[] = "@(#)db_byteorder.c 10.4 (Sleepycat) 9/4/97";
static const char sccsid[] = "@(#)db_byteorder.c 10.5 (Sleepycat) 4/10/98";
#endif /* not lint */
#ifndef NO_SYSTEM_INCLUDES

View File

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

View File

@ -1,7 +1,7 @@
/*-
* See the file LICENSE for redistribution information.
*
* Copyright (c) 1996, 1997
* Copyright (c) 1996, 1997, 1998
* Sleepycat Software. All rights reserved.
*/
/*
@ -43,7 +43,7 @@
#include "config.h"
#ifndef lint
static const char sccsid[] = "@(#)db_log2.c 10.3 (Sleepycat) 6/21/97";
static const char sccsid[] = "@(#)db_log2.c 10.5 (Sleepycat) 4/26/98";
#endif /* not lint */
#ifndef NO_SYSTEM_INCLUDES
@ -63,6 +63,7 @@ __db_log2(num)
u_int32_t i, limit;
limit = 1;
for (i = 0; limit < num; limit = limit << 1, i++);
for (i = 0; limit < num; limit = limit << 1, i++)
;
return (i);
}

File diff suppressed because it is too large Load Diff

View File

@ -1,21 +1,21 @@
/*-
* See the file LICENSE for redistribution information.
*
* Copyright (c) 1996, 1997
* Copyright (c) 1996, 1997, 1998
* Sleepycat Software. All rights reserved.
*/
#include "config.h"
#ifndef lint
static const char sccsid[] = "@(#)db_salloc.c 10.6 (Sleepycat) 7/5/97";
static const char sccsid[] = "@(#)db_salloc.c 10.13 (Sleepycat) 5/10/98";
#endif /* not lint */
#ifndef NO_SYSTEM_INCLUDES
#include <sys/types.h>
#include <errno.h>
#include <stdio.h>
#include <string.h>
#endif
#include "db_int.h"
@ -109,11 +109,13 @@ __db_shalloc(p, len, align, retp)
*(void **)retp = rp;
#define SHALLOC_FRAGMENT 32
/*
* If there are at least 32 bytes of additional memory, divide
* the chunk into two chunks.
* If there are at least SHALLOC_FRAGMENT additional bytes of
* memory, divide the chunk into two chunks.
*/
if ((u_int8_t *)rp >= (u_int8_t *)&elp->links + 32) {
if ((u_int8_t *)rp >=
(u_int8_t *)&elp->links + SHALLOC_FRAGMENT) {
sp = rp;
*--sp = elp->len -
((u_int8_t *)rp - (u_int8_t *)&elp->links);
@ -136,7 +138,7 @@ __db_shalloc(p, len, align, retp)
return (0);
}
/* Nothing found large enough; need to figure out how to grow region. */
/* Nothing found large enough; need to grow the region. */
return (ENOMEM);
}
@ -159,12 +161,18 @@ __db_shalloc_free(regionp, ptr)
* Step back over flagged length fields to find the beginning of
* the object and its real size.
*/
for (sp = (size_t *)ptr; sp[-1] == ILLEGAL_SIZE; --sp);
for (sp = (size_t *)ptr; sp[-1] == ILLEGAL_SIZE; --sp)
;
ptr = sp;
newp = (struct __data *)((u_int8_t *)ptr - sizeof(size_t));
free_size = newp->len;
/* Trash the returned memory. */
#ifdef DIAGNOSTIC
memset(ptr, 0xff, free_size);
#endif
/*
* Walk the list, looking for where this entry goes.
*
@ -177,7 +185,8 @@ __db_shalloc_free(regionp, ptr)
hp = (struct __head *)regionp;
for (elp = SH_LIST_FIRST(hp, __data), lastp = NULL;
elp != NULL && (void *)elp < (void *)ptr;
lastp = elp, elp = SH_LIST_NEXT(elp, links, __data));
lastp = elp, elp = SH_LIST_NEXT(elp, links, __data))
;
/*
* Elp is either NULL (we reached the end of the list), or the slot
@ -259,32 +268,34 @@ __db_shsizeof(ptr)
* Step back over flagged length fields to find the beginning of
* the object and its real size.
*/
for (sp = (size_t *)ptr; sp[-1] == ILLEGAL_SIZE; --sp);
for (sp = (size_t *)ptr; sp[-1] == ILLEGAL_SIZE; --sp)
;
elp = (struct __data *)((u_int8_t *)sp - sizeof(size_t));
return (elp->len);
}
#ifdef DEBUG
/*
* __db_shalloc_dump --
*
* PUBLIC: void __db_shalloc_dump __P((FILE *, void *));
* PUBLIC: void __db_shalloc_dump __P((void *, FILE *));
*/
void
__db_shalloc_dump(fp, addr)
FILE *fp;
__db_shalloc_dump(addr, fp)
void *addr;
FILE *fp;
{
struct __data *elp;
/* Make it easy to call from the debugger. */
if (fp == NULL)
fp = stderr;
fprintf(fp, "%s\nMemory free list\n", DB_LINE);
for (elp = SH_LIST_FIRST((struct __head *)addr, __data);
elp != NULL;
elp = SH_LIST_NEXT(elp, links, __data))
fprintf(fp, "%#lx: %lu\t", (u_long)elp, (u_long)elp->len);
fprintf(fp, "\n");
}
#endif

View File

@ -1,14 +1,14 @@
/*-
* See the file LICENSE for redistribution information.
*
* Copyright (c) 1996, 1997
* Copyright (c) 1996, 1997, 1998
* Sleepycat Software. All rights reserved.
*/
#include "config.h"
#ifndef lint
static const char sccsid[] = "@(#)db_shash.c 10.4 (Sleepycat) 1/8/98";
static const char sccsid[] = "@(#)db_shash.c 10.9 (Sleepycat) 4/10/98";
#endif /* not lint */
#ifndef NO_SYSTEM_INCLUDES
@ -19,19 +19,56 @@ static const char sccsid[] = "@(#)db_shash.c 10.4 (Sleepycat) 1/8/98";
#include "shqueue.h"
#include "common_ext.h"
/* Powers-of-2 and close-by prime number pairs. */
/*
* Table of good hash values. Up to ~250,000 buckets, we use powers of 2.
* After that, we slow the rate of increase by half. For each choice, we
* then use a nearby prime number as the hash value.
*
* If a terabyte is the maximum cache we'll see, and we assume there are
* 10 1K buckets on each hash chain, then 107374182 is the maximum number
* of buckets we'll ever need.
*/
static const struct {
u_int power;
u_int prime;
u_int32_t power;
u_int32_t prime;
} list[] = {
{ 64, 67},
{ 128, 131},
{ 256, 257},
{ 512, 521},
{1024, 1031},
{2048, 2053},
{4096, 4099},
{8192, 8191},
{ 64, 67}, /* 2^6 */
{ 128, 131}, /* 2^7 */
{ 256, 257}, /* 2^8 */
{ 512, 521}, /* 2^9 */
{ 1024, 1031}, /* 2^10 */
{ 2048, 2053}, /* 2^11 */
{ 4096, 4099}, /* 2^12 */
{ 8192, 8191}, /* 2^13 */
{ 16384, 16381}, /* 2^14 */
{ 32768, 32771}, /* 2^15 */
{ 65536, 65537}, /* 2^16 */
{ 131072, 131071}, /* 2^17 */
{ 262144, 262147}, /* 2^18 */
{ 393216, 393209}, /* 2^18 + 2^18/2 */
{ 524288, 524287}, /* 2^19 */
{ 786432, 786431}, /* 2^19 + 2^19/2 */
{ 1048576, 1048573}, /* 2^20 */
{ 1572864, 1572869}, /* 2^20 + 2^20/2 */
{ 2097152, 2097169}, /* 2^21 */
{ 3145728, 3145721}, /* 2^21 + 2^21/2 */
{ 4194304, 4194301}, /* 2^22 */
{ 6291456, 6291449}, /* 2^22 + 2^22/2 */
{ 8388608, 8388617}, /* 2^23 */
{ 12582912, 12582917}, /* 2^23 + 2^23/2 */
{ 16777216, 16777213}, /* 2^24 */
{ 25165824, 25165813}, /* 2^24 + 2^24/2 */
{ 33554432, 33554393}, /* 2^25 */
{ 50331648, 50331653}, /* 2^25 + 2^25/2 */
{ 67108864, 67108859}, /* 2^26 */
{ 100663296, 100663291}, /* 2^26 + 2^26/2 */
{ 134217728, 134217757}, /* 2^27 */
{ 201326592, 201326611}, /* 2^27 + 2^27/2 */
{ 268435456, 268435459}, /* 2^28 */
{ 402653184, 402653189}, /* 2^28 + 2^28/2 */
{ 536870912, 536870909}, /* 2^29 */
{ 805306368, 805306357}, /* 2^29 + 2^29/2 */
{1073741824, 1073741827}, /* 2^30 */
{0, 0}
};
@ -39,19 +76,18 @@ static const struct {
* __db_tablesize --
* Choose a size for the hash table.
*
* PUBLIC: int __db_tablesize __P((u_int));
* PUBLIC: int __db_tablesize __P((u_int32_t));
*/
int
__db_tablesize(n_buckets)
u_int n_buckets;
u_int32_t n_buckets;
{
int i;
/*
* We try to be clever about how big we make the hash tables. Pick
* a prime number close to the "suggested" number of elements that
* will be in the hash table. We shoot for minimum collisions (i.e.
* one element in each bucket). We use 64 as the minimum table size.
* We try to be clever about how big we make the hash tables. Use a
* prime number close to the "suggested" number of elements that will
* be in the hash table. Use 64 as the minimum hash table size.
*
* Ref: Sedgewick, Algorithms in C, "Hash Functions"
*/
@ -73,14 +109,14 @@ __db_tablesize(n_buckets)
* __db_hashinit --
* Initialize a hash table that resides in shared memory.
*
* PUBLIC: void __db_hashinit __P((void *, int));
* PUBLIC: void __db_hashinit __P((void *, u_int32_t));
*/
void
__db_hashinit(begin, nelements)
void *begin;
int nelements;
u_int32_t nelements;
{
int i;
u_int32_t i;
SH_TAILQ_HEAD(hash_head) *headp;
headp = (struct hash_head *)begin;

View File

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

225
db2/db.h
View File

@ -1,10 +1,10 @@
/*-
* See the file LICENSE for redistribution information.
*
* Copyright (c) 1996, 1997
* Copyright (c) 1996, 1997, 1998
* Sleepycat Software. All rights reserved.
*
* @(#)db.h.src 10.102 (Sleepycat) 1/18/98
* @(#)db.h.src 10.131 (Sleepycat) 6/2/98
*/
#ifndef _DB_H_
@ -54,8 +54,7 @@
*
* !!!
* We also provide the standard u_int, u_long etc., if they're not provided
* by the system. This isn't completely necessary, but the example programs
* need them.
* by the system.
*/
#ifndef __BIT_TYPES_DEFINED__
#define __BIT_TYPES_DEFINED__
@ -72,9 +71,9 @@
#define DB_VERSION_MAJOR 2
#define DB_VERSION_MINOR 3
#define DB_VERSION_PATCH 16
#define DB_VERSION_STRING "Sleepycat Software: DB 2.3.16: (1/19/98)"
#define DB_VERSION_MINOR 4
#define DB_VERSION_PATCH 14
#define DB_VERSION_STRING "Sleepycat Software: DB 2.4.14: (6/2/98)"
typedef u_int32_t db_pgno_t; /* Page number type. */
typedef u_int16_t db_indx_t; /* Page offset type. */
@ -95,6 +94,7 @@ struct __db_bt_stat; typedef struct __db_bt_stat DB_BTREE_STAT;
struct __db_dbt; typedef struct __db_dbt DBT;
struct __db_env; typedef struct __db_env DB_ENV;
struct __db_info; typedef struct __db_info DB_INFO;
struct __db_lock_stat; typedef struct __db_lock_stat DB_LOCK_STAT;
struct __db_lockregion; typedef struct __db_lockregion DB_LOCKREGION;
struct __db_lockreq; typedef struct __db_lockreq DB_LOCKREQ;
struct __db_locktab; typedef struct __db_locktab DB_LOCKTAB;
@ -102,6 +102,7 @@ struct __db_log; typedef struct __db_log DB_LOG;
struct __db_log_stat; typedef struct __db_log_stat DB_LOG_STAT;
struct __db_lsn; typedef struct __db_lsn DB_LSN;
struct __db_mpool; typedef struct __db_mpool DB_MPOOL;
struct __db_mpool_finfo;typedef struct __db_mpool_finfo DB_MPOOL_FINFO;
struct __db_mpool_fstat;typedef struct __db_mpool_fstat DB_MPOOL_FSTAT;
struct __db_mpool_stat; typedef struct __db_mpool_stat DB_MPOOL_STAT;
struct __db_mpoolfile; typedef struct __db_mpoolfile DB_MPOOLFILE;
@ -134,7 +135,7 @@ struct __db_dbt {
* There are a set of functions that the application can replace with its
* own versions, and some other knobs which can be turned at run-time.
*/
#define DB_FUNC_CALLOC 1 /* ANSI C calloc. */
#define DB_FUNC_CALLOC 1 /* DELETED: ANSI C calloc. */
#define DB_FUNC_CLOSE 2 /* POSIX 1003.1 close. */
#define DB_FUNC_DIRFREE 3 /* DB: free directory list. */
#define DB_FUNC_DIRLIST 4 /* DB: create directory list. */
@ -149,12 +150,18 @@ struct __db_dbt {
#define DB_FUNC_REALLOC 13 /* ANSI C realloc. */
#define DB_FUNC_SEEK 14 /* POSIX 1003.1 lseek. */
#define DB_FUNC_SLEEP 15 /* DB: sleep secs/usecs. */
#define DB_FUNC_STRDUP 16 /* DB: strdup(3). */
#define DB_FUNC_STRDUP 16 /* DELETED: DB: strdup(3). */
#define DB_FUNC_UNLINK 17 /* POSIX 1003.1 unlink. */
#define DB_FUNC_UNMAP 18 /* DB: unmap shared memory file. */
#define DB_FUNC_WRITE 19 /* POSIX 1003.1 write. */
#define DB_FUNC_YIELD 20 /* DB: yield thread to scheduler. */
#define DB_TSL_SPINS 21 /* DB: initialize spin count. */
#define DB_FUNC_RUNLINK 22 /* DB: remove a shared region. */
#define DB_REGION_ANON 23 /* DB: anonymous, unnamed regions. */
#define DB_REGION_INIT 24 /* DB: page-fault regions in create. */
#define DB_REGION_NAME 25 /* DB: anonymous, named regions. */
#define DB_MUTEXLOCKS 26 /* DB: turn off all mutex locks. */
#define DB_PAGEYIELD 27 /* DB: yield the CPU on pool get. */
/*
* Database configuration and initialization.
@ -162,52 +169,51 @@ struct __db_dbt {
/*
* Flags understood by both db_open(3) and db_appinit(3).
*/
#define DB_CREATE 0x00001 /* O_CREAT: create file as necessary. */
#define DB_NOMMAP 0x00002 /* Don't mmap underlying file. */
#define DB_THREAD 0x00004 /* Free-thread DB package handles. */
#define DB_CREATE 0x000001 /* O_CREAT: create file as necessary. */
#define DB_NOMMAP 0x000002 /* Don't mmap underlying file. */
#define DB_THREAD 0x000004 /* Free-thread DB package handles. */
/*
* Flags understood by db_appinit(3).
*
* DB_MUTEXDEBUG is internal only, and not documented.
*/
/* 0x00007 COMMON MASK. */
#define DB_INIT_LOCK 0x00008 /* Initialize locking. */
#define DB_INIT_LOG 0x00010 /* Initialize logging. */
#define DB_INIT_MPOOL 0x00020 /* Initialize mpool. */
#define DB_INIT_TXN 0x00040 /* Initialize transactions. */
#define DB_MPOOL_PRIVATE 0x00080 /* Mpool: private memory pool. */
#define DB_MUTEXDEBUG 0x00100 /* Do not get/set mutexes in regions. */
#define DB_RECOVER 0x00200 /* Run normal recovery. */
#define DB_RECOVER_FATAL 0x00400 /* Run catastrophic recovery. */
#define DB_TXN_NOSYNC 0x00800 /* Do not sync log on commit. */
#define DB_USE_ENVIRON 0x01000 /* Use the environment. */
#define DB_USE_ENVIRON_ROOT 0x02000 /* Use the environment if root. */
/* 0x000007 COMMON MASK. */
#define DB_INIT_LOCK 0x000008 /* Initialize locking. */
#define DB_INIT_LOG 0x000010 /* Initialize logging. */
#define DB_INIT_MPOOL 0x000020 /* Initialize mpool. */
#define DB_INIT_TXN 0x000040 /* Initialize transactions. */
#define DB_MPOOL_PRIVATE 0x000080 /* Mpool: private memory pool. */
#define __UNUSED_100 0x000100
#define DB_RECOVER 0x000200 /* Run normal recovery. */
#define DB_RECOVER_FATAL 0x000400 /* Run catastrophic recovery. */
#define DB_TXN_NOSYNC 0x000800 /* Do not sync log on commit. */
#define DB_USE_ENVIRON 0x001000 /* Use the environment. */
#define DB_USE_ENVIRON_ROOT 0x002000 /* Use the environment if root. */
/* CURRENTLY UNUSED LOCK FLAGS. */
#define DB_TXN_LOCK_2PL 0x00000 /* Two-phase locking. */
#define DB_TXN_LOCK_OPTIMISTIC 0x00000 /* Optimistic locking. */
#define DB_TXN_LOCK_MASK 0x00000 /* Lock flags mask. */
#define DB_TXN_LOCK_2PL 0x000000 /* Two-phase locking. */
#define DB_TXN_LOCK_OPTIMIST 0x000000 /* Optimistic locking. */
#define DB_TXN_LOCK_MASK 0x000000 /* Lock flags mask. */
/* CURRENTLY UNUSED LOG FLAGS. */
#define DB_TXN_LOG_REDO 0x00000 /* Redo-only logging. */
#define DB_TXN_LOG_UNDO 0x00000 /* Undo-only logging. */
#define DB_TXN_LOG_UNDOREDO 0x00000 /* Undo/redo write-ahead logging. */
#define DB_TXN_LOG_MASK 0x00000 /* Log flags mask. */
#define DB_TXN_LOG_REDO 0x000000 /* Redo-only logging. */
#define DB_TXN_LOG_UNDO 0x000000 /* Undo-only logging. */
#define DB_TXN_LOG_UNDOREDO 0x000000 /* Undo/redo write-ahead logging. */
#define DB_TXN_LOG_MASK 0x000000 /* Log flags mask. */
/*
* Flags understood by db_open(3).
*
* DB_EXCL and DB_TEMPORARY are internal only, and not documented.
* DB_SEQUENTIAL is currently internal, but likely to be exported some day.
* DB_EXCL and DB_TEMPORARY are internal only, and are not documented.
* DB_SEQUENTIAL is currently internal, but may be exported some day.
*/
/* 0x00007 COMMON MASK. */
/* 0x07fff ALREADY USED. */
#define DB_EXCL 0x08000 /* O_EXCL: exclusive open. */
#define DB_RDONLY 0x10000 /* O_RDONLY: read-only. */
#define DB_SEQUENTIAL 0x20000 /* Indicate sequential access. */
#define DB_TEMPORARY 0x40000 /* Remove on last close. */
#define DB_TRUNCATE 0x80000 /* O_TRUNCATE: replace existing DB. */
/* 0x000007 COMMON MASK. */
/* 0x003fff ALREADY USED. */
#define __UNUSED_4000 0x004000
#define DB_EXCL 0x008000 /* O_EXCL: exclusive open. */
#define DB_RDONLY 0x010000 /* O_RDONLY: read-only. */
#define DB_SEQUENTIAL 0x020000 /* Indicate sequential access. */
#define DB_TEMPORARY 0x040000 /* Remove on last close. */
#define DB_TRUNCATE 0x080000 /* O_TRUNCATE: replace existing DB. */
/*
* Deadlock detector modes; used in the DBENV structure to configure the
@ -240,9 +246,9 @@ struct __db_env {
/* Locking. */
DB_LOCKTAB *lk_info; /* Return from lock_open(). */
u_int8_t *lk_conflicts; /* Two dimensional conflict matrix. */
int lk_modes; /* Number of lock modes in table. */
u_int lk_max; /* Maximum number of locks. */
u_int32_t lk_detect; /* Deadlock detect on every conflict. */
u_int32_t lk_modes; /* Number of lock modes in table. */
u_int32_t lk_max; /* Maximum number of locks. */
u_int32_t lk_detect; /* Deadlock detect on all conflicts. */
/* Logging. */
DB_LOG *lg_info; /* Return from log_open(). */
@ -255,7 +261,7 @@ struct __db_env {
/* Transactions. */
DB_TXNMGR *tx_info; /* Return from txn_open(). */
unsigned int tx_max; /* Maximum number of transactions. */
u_int32_t tx_max; /* Maximum number of transactions. */
int (*tx_recover) /* Dispatch function for recovery. */
__P((DB_LOG *, DBT *, DB_LSN *, int, void *));
@ -300,16 +306,16 @@ struct __db_info {
void *(*db_malloc) __P((size_t));
/* Btree access method. */
int bt_maxkey; /* Maximum keys per page. */
int bt_minkey; /* Minimum keys per page. */
u_int32_t bt_maxkey; /* Maximum keys per page. */
u_int32_t bt_minkey; /* Minimum keys per page. */
int (*bt_compare) /* Comparison function. */
__P((const DBT *, const DBT *));
size_t (*bt_prefix) /* Prefix function. */
__P((const DBT *, const DBT *));
/* Hash access method. */
unsigned int h_ffactor; /* Fill factor. */
unsigned int h_nelem; /* Number of elements. */
u_int32_t h_ffactor; /* Fill factor. */
u_int32_t h_nelem; /* Number of elements. */
u_int32_t (*h_hash) /* Hash function. */
__P((const void *, u_int32_t));
@ -353,6 +359,7 @@ struct __db_info {
#define DB_SET 0x010000 /* c_get(), log_get() */
#define DB_SET_RANGE 0x020000 /* c_get() */
#define DB_SET_RECNO 0x040000 /* c_get() */
#define DB_CURLSN 0x080000 /* log_put() */
/*
* DB (user visible) error return codes.
@ -435,14 +442,14 @@ struct __db {
void *(*db_malloc) __P((size_t));
/* Functions. */
int (*close) __P((DB *, int));
int (*close) __P((DB *, u_int32_t));
int (*cursor) __P((DB *, DB_TXN *, DBC **));
int (*del) __P((DB *, DB_TXN *, DBT *, int));
int (*del) __P((DB *, DB_TXN *, DBT *, u_int32_t));
int (*fd) __P((DB *, int *));
int (*get) __P((DB *, DB_TXN *, DBT *, DBT *, int));
int (*put) __P((DB *, DB_TXN *, DBT *, DBT *, int));
int (*stat) __P((DB *, void *, void *(*)(size_t), int));
int (*sync) __P((DB *, int));
int (*get) __P((DB *, DB_TXN *, DBT *, DBT *, u_int32_t));
int (*put) __P((DB *, DB_TXN *, DBT *, DBT *, u_int32_t));
int (*stat) __P((DB *, void *, void *(*)(size_t), u_int32_t));
int (*sync) __P((DB *, u_int32_t));
#define DB_AM_DUP 0x000001 /* DB_DUP (internal). */
#define DB_AM_INMEM 0x000002 /* In-memory; no sync on close. */
@ -483,9 +490,9 @@ struct __dbc {
void *internal; /* Access method private. */
int (*c_close) __P((DBC *));
int (*c_del) __P((DBC *, int));
int (*c_get) __P((DBC *, DBT *, DBT *, int));
int (*c_put) __P((DBC *, DBT *, DBT *, int));
int (*c_del) __P((DBC *, u_int32_t));
int (*c_get) __P((DBC *, DBT *, DBT *, u_int32_t));
int (*c_put) __P((DBC *, DBT *, DBT *, u_int32_t));
};
/* Btree/recno statistics structure. */
@ -524,10 +531,11 @@ struct __db_bt_stat {
#if defined(__cplusplus)
extern "C" {
#endif
int db_appinit __P((const char *, char * const *, DB_ENV *, int));
int db_appinit __P((const char *, char * const *, DB_ENV *, u_int32_t));
int db_appexit __P((DB_ENV *));
int db_jump_set __P((void *, int));
int db_open __P((const char *, DBTYPE, int, int, DB_ENV *, DB_INFO *, DB **));
int db_open __P((const char *,
DBTYPE, u_int32_t, int, DB_ENV *, DB_INFO *, DB **));
int db_value_set __P((int, int));
char *db_version __P((int *, int *, int *));
#if defined(__cplusplus)
@ -575,6 +583,21 @@ typedef enum {
DB_LOCK_IWR /* Intent to read and write. */
} db_lockmode_t;
/*
* Status of a lock.
*/
typedef enum {
DB_LSTAT_ABORTED, /* Lock belongs to an aborted txn. */
DB_LSTAT_ERR, /* Lock is bad. */
DB_LSTAT_FREE, /* Lock is unallocated. */
DB_LSTAT_HELD, /* Lock is currently held. */
DB_LSTAT_NOGRANT, /* Lock was not granted. */
DB_LSTAT_PENDING, /* Lock was waiting and has been
* promoted; waiting for the owner
* to run and upgrade it to held. */
DB_LSTAT_WAITING /* Lock is on the wait queue. */
} db_status_t;
/* Lock request structure. */
struct __db_lockreq {
db_lockop_t op; /* Operation. */
@ -596,19 +619,38 @@ extern const u_int8_t db_rw_conflicts[];
#define DB_LOCK_RIW_N 6
extern const u_int8_t db_riw_conflicts[];
struct __db_lock_stat {
u_int32_t st_magic; /* Lock file magic number. */
u_int32_t st_version; /* Lock file version number. */
u_int32_t st_maxlocks; /* Maximum number of locks in table. */
u_int32_t st_nmodes; /* Number of lock modes. */
u_int32_t st_numobjs; /* Number of objects. */
u_int32_t st_nlockers; /* Number of lockers. */
u_int32_t st_nconflicts; /* Number of lock conflicts. */
u_int32_t st_nrequests; /* Number of lock gets. */
u_int32_t st_nreleases; /* Number of lock puts. */
u_int32_t st_ndeadlocks; /* Number of lock deadlocks. */
u_int32_t st_region_wait; /* Region lock granted after wait. */
u_int32_t st_region_nowait; /* Region lock granted without wait. */
u_int32_t st_refcnt; /* Region reference count. */
u_int32_t st_regsize; /* Region size. */
};
#if defined(__cplusplus)
extern "C" {
#endif
int lock_close __P((DB_LOCKTAB *));
int lock_detect __P((DB_LOCKTAB *, int, int));
int lock_detect __P((DB_LOCKTAB *, u_int32_t, u_int32_t));
int lock_get __P((DB_LOCKTAB *,
u_int32_t, int, const DBT *, db_lockmode_t, DB_LOCK *));
u_int32_t, u_int32_t, const DBT *, db_lockmode_t, DB_LOCK *));
int lock_id __P((DB_LOCKTAB *, u_int32_t *));
int lock_open __P((const char *, int, int, DB_ENV *, DB_LOCKTAB **));
int lock_open __P((const char *,
u_int32_t, int, DB_ENV *, DB_LOCKTAB **));
int lock_put __P((DB_LOCKTAB *, DB_LOCK));
int lock_stat __P((DB_LOCKTAB *, DB_LOCK_STAT **, void *(*)(size_t)));
int lock_unlink __P((const char *, int, DB_ENV *));
int lock_vec __P((DB_LOCKTAB *,
u_int32_t, int, DB_LOCKREQ *, int, DB_LOCKREQ **));
u_int32_t, u_int32_t, DB_LOCKREQ *, int, DB_LOCKREQ **));
#if defined(__cplusplus)
}
#endif
@ -651,19 +693,21 @@ struct __db_log_stat {
u_int32_t st_region_nowait; /* Region lock granted without wait. */
u_int32_t st_cur_file; /* Current log file number. */
u_int32_t st_cur_offset; /* Current log file offset. */
u_int32_t st_refcnt; /* Region reference count. */
u_int32_t st_regsize; /* Region size. */
};
#if defined(__cplusplus)
extern "C" {
#endif
int log_archive __P((DB_LOG *, char **[], int, void *(*)(size_t)));
int log_archive __P((DB_LOG *, char **[], u_int32_t, void *(*)(size_t)));
int log_close __P((DB_LOG *));
int log_compare __P((const DB_LSN *, const DB_LSN *));
int log_file __P((DB_LOG *, const DB_LSN *, char *, size_t));
int log_flush __P((DB_LOG *, const DB_LSN *));
int log_get __P((DB_LOG *, DB_LSN *, DBT *, int));
int log_open __P((const char *, int, int, DB_ENV *, DB_LOG **));
int log_put __P((DB_LOG *, DB_LSN *, const DBT *, int));
int log_get __P((DB_LOG *, DB_LSN *, DBT *, u_int32_t));
int log_open __P((const char *, u_int32_t, int, DB_ENV *, DB_LOG **));
int log_put __P((DB_LOG *, DB_LSN *, const DBT *, u_int32_t));
int log_register __P((DB_LOG *, DB *, const char *, DBTYPE, u_int32_t *));
int log_stat __P((DB_LOG *, DB_LOG_STAT **, void *(*)(size_t)));
int log_unlink __P((const char *, int, DB_ENV *));
@ -705,6 +749,17 @@ struct __db_mpool_stat {
u_int32_t st_page_trickle; /* Pages written by memp_trickle. */
u_int32_t st_region_wait; /* Region lock granted after wait. */
u_int32_t st_region_nowait; /* Region lock granted without wait. */
u_int32_t st_refcnt; /* Region reference count. */
u_int32_t st_regsize; /* Region size. */
};
/* Mpool file open information structure. */
struct __db_mpool_finfo {
int ftype; /* File type. */
DBT *pgcookie; /* Byte-string passed to pgin/pgout. */
u_int8_t *fileid; /* Unique file ID. */
int32_t lsn_offset; /* LSN offset in page. */
u_int32_t clear_len; /* Cleared length on created pages. */
};
/* Mpool file statistics structure. */
@ -724,13 +779,13 @@ extern "C" {
#endif
int memp_close __P((DB_MPOOL *));
int memp_fclose __P((DB_MPOOLFILE *));
int memp_fget __P((DB_MPOOLFILE *, db_pgno_t *, int, void *));
int memp_fget __P((DB_MPOOLFILE *, db_pgno_t *, u_int32_t, void *));
int memp_fopen __P((DB_MPOOL *, const char *,
int, int, int, size_t, int, DBT *, u_int8_t *, DB_MPOOLFILE **));
int memp_fput __P((DB_MPOOLFILE *, void *, int));
int memp_fset __P((DB_MPOOLFILE *, void *, int));
u_int32_t, int, size_t, DB_MPOOL_FINFO *, DB_MPOOLFILE **));
int memp_fput __P((DB_MPOOLFILE *, void *, u_int32_t));
int memp_fset __P((DB_MPOOLFILE *, void *, u_int32_t));
int memp_fsync __P((DB_MPOOLFILE *));
int memp_open __P((const char *, int, int, DB_ENV *, DB_MPOOL **));
int memp_open __P((const char *, u_int32_t, int, DB_ENV *, DB_MPOOL **));
int memp_register __P((DB_MPOOL *, int,
int (*)(db_pgno_t, void *, DBT *),
int (*)(db_pgno_t, void *, DBT *)));
@ -774,7 +829,12 @@ struct __db_txn_stat {
u_int32_t st_nbegins; /* number of begun transactions */
u_int32_t st_ncommits; /* number of committed transactions */
u_int32_t st_nactive; /* number of active transactions */
DB_TXN_ACTIVE *st_txnarray; /* array of active transactions */
DB_TXN_ACTIVE
*st_txnarray; /* array of active transactions */
u_int32_t st_region_wait; /* Region lock granted after wait. */
u_int32_t st_region_nowait; /* Region lock granted without wait. */
u_int32_t st_refcnt; /* Region reference count. */
u_int32_t st_regsize; /* Region size. */
};
#if defined(__cplusplus)
@ -782,11 +842,11 @@ extern "C" {
#endif
int txn_abort __P((DB_TXN *));
int txn_begin __P((DB_TXNMGR *, DB_TXN *, DB_TXN **));
int txn_checkpoint __P((const DB_TXNMGR *, int, int));
int txn_checkpoint __P((const DB_TXNMGR *, u_int32_t, u_int32_t));
int txn_commit __P((DB_TXN *));
int txn_close __P((DB_TXNMGR *));
u_int32_t txn_id __P((DB_TXN *));
int txn_open __P((const char *, int, int, DB_ENV *, DB_TXNMGR **));
int txn_open __P((const char *, u_int32_t, int, DB_ENV *, DB_TXNMGR **));
int txn_prepare __P((DB_TXN *));
int txn_stat __P((DB_TXNMGR *, DB_TXN_STAT **, void *(*)(size_t)));
int txn_unlink __P((const char *, int, DB_ENV *));
@ -810,10 +870,17 @@ int txn_unlink __P((const char *, int, DB_ENV *));
*/
#define DBM_SUFFIX ".db"
#if defined(_XPG4_2)
typedef struct {
char *dptr;
size_t dsize;
} datum;
#else
typedef struct {
char *dptr;
int dsize;
} datum;
#endif
/*
* Translate DBM calls into DB calls so that DB doesn't step on the
@ -894,7 +961,7 @@ typedef enum {
typedef struct entry {
char *key;
void *data;
char *data;
} ENTRY;
/*
@ -909,7 +976,7 @@ typedef struct entry {
#if defined(__cplusplus)
extern "C" {
#endif
int __db_hcreate __P((unsigned int));
int __db_hcreate __P((size_t));
void __db_hdestroy __P((void));
ENTRY *__db_hsearch __P((ENTRY, ACTION));
#if defined(__cplusplus)

View File

@ -1,7 +1,7 @@
/*-
* See the file LICENSE for redistribution information.
*
* Copyright (c) 1996, 1997
* Copyright (c) 1996, 1997, 1998
* Sleepycat Software. All rights reserved.
*/
/*
@ -44,20 +44,16 @@
#include "config.h"
#ifndef lint
static const char sccsid[] = "@(#)db.c 10.45 (Sleepycat) 12/4/97";
static const char sccsid[] = "@(#)db.c 10.57 (Sleepycat) 5/7/98";
#endif /* not lint */
#ifndef NO_SYSTEM_INCLUDES
#include <sys/types.h>
#include <sys/stat.h>
#include <errno.h>
#include <fcntl.h>
#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#endif
#include "db_int.h"
@ -71,7 +67,7 @@ static const char sccsid[] = "@(#)db.c 10.45 (Sleepycat) 12/4/97";
#include "db_am.h"
#include "common_ext.h"
static int db_close __P((DB *, int));
static int db_close __P((DB *, u_int32_t));
static int db_fd __P((DB *, int *));
/*
@ -99,7 +95,8 @@ int
db_open(fname, type, flags, mode, dbenv, dbinfo, dbpp)
const char *fname;
DBTYPE type;
int flags, mode;
u_int32_t flags;
int mode;
DB_ENV *dbenv;
DB_INFO *dbinfo;
DB **dbpp;
@ -108,6 +105,7 @@ db_open(fname, type, flags, mode, dbenv, dbinfo, dbpp)
DB *dbp;
DBT pgcookie;
DB_ENV *envp, t_dbenv;
DB_MPOOL_FINFO finfo;
DB_PGINFO pginfo;
HASHHDR *hashm;
size_t cachesize;
@ -125,12 +123,28 @@ db_open(fname, type, flags, mode, dbenv, dbinfo, dbpp)
if ((ret = __db_fchk(dbenv, "db_open", flags, OKFLAGS)) != 0)
return (ret);
if (dbenv != NULL &&
LF_ISSET(DB_THREAD) && !F_ISSET(dbenv, DB_ENV_THREAD)) {
__db_err(dbenv, "environment not created using DB_THREAD");
if (dbenv != NULL) {
/*
* You can't specify threads during the db_open() if the
* environment wasn't configured with them.
*/
if (LF_ISSET(DB_THREAD) && !F_ISSET(dbenv, DB_ENV_THREAD)) {
__db_err(dbenv,
"environment not created using DB_THREAD");
return (EINVAL);
}
/*
* Specifying a cachesize to db_open(3), after creating an
* environment, is a common mistake.
*/
if (dbinfo != NULL && dbinfo->db_cachesize != 0) {
__db_err(dbenv,
"cachesize will be ignored if environment exists");
return (EINVAL);
}
}
/* Initialize for error return. */
fd = -1;
need_fileid = 1;
@ -203,7 +217,7 @@ db_open(fname, type, flags, mode, dbenv, dbinfo, dbpp)
/* Fill in the default file mode. */
if (mode == 0)
mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP;
mode = __db_omode("rwrw--");
/* Check if the user wants us to swap byte order. */
if (dbinfo != NULL)
@ -230,7 +244,7 @@ db_open(fname, type, flags, mode, dbenv, dbinfo, dbpp)
if (fname != NULL && fname[0] != '\0') {
/* Get the real file name. */
if ((ret = __db_appname(dbenv,
DB_APP_DATA, NULL, fname, NULL, &real_name)) != 0)
DB_APP_DATA, NULL, fname, 0, NULL, &real_name)) != 0)
goto err;
/*
@ -454,22 +468,6 @@ empty: /*
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,
* created buffer pool.
@ -499,10 +497,28 @@ empty: /*
envp = dbenv;
restore = 1;
}
/*
* Set and/or correct the cache size; must be a multiple of
* the page size.
*/
if (dbinfo == NULL || dbinfo->db_cachesize == 0)
cachesize = dbp->pgsize * DB_MINCACHE;
else {
cachesize = dbinfo->db_cachesize;
if (cachesize & (dbp->pgsize - 1))
cachesize +=
(~cachesize & (dbp->pgsize - 1)) + 1;
if (cachesize < dbp->pgsize * DB_MINCACHE)
cachesize = dbp->pgsize * DB_MINCACHE;
if (cachesize < 20 * 1024)
cachesize = 20 * 1024;
}
envp->mp_size = cachesize;
if ((ret = memp_open(NULL, DB_CREATE | DB_MPOOL_PRIVATE |
(F_ISSET(dbp, DB_AM_THREAD) ? DB_THREAD : 0),
S_IRUSR | S_IWUSR, envp, &dbp->mp)) != 0)
__db_omode("rw----"), envp, &dbp->mp)) != 0)
goto err;
if (restore)
*dbenv = t_dbenv;
@ -566,9 +582,18 @@ empty: /*
pgcookie.data = &pginfo;
pgcookie.size = sizeof(DB_PGINFO);
if ((ret = memp_fopen(dbp->mp, fname, ftype,
F_ISSET(dbp, DB_AM_RDONLY) ? DB_RDONLY : 0, 0, dbp->pgsize,
0, &pgcookie, dbp->lock.fileid, &dbp->mpf)) != 0)
/*
* Set up additional memp_fopen information.
*/
memset(&finfo, 0, sizeof(finfo));
finfo.ftype = ftype;
finfo.pgcookie = &pgcookie;
finfo.fileid = dbp->lock.fileid;
finfo.lsn_offset = 0;
finfo.clear_len = DB_PAGE_CLEAR_LEN;
if ((ret = memp_fopen(dbp->mp, fname,
F_ISSET(dbp, DB_AM_RDONLY) ? DB_RDONLY : 0,
0, dbp->pgsize, &finfo, &dbp->mpf)) != 0)
goto err;
/*
@ -673,7 +698,7 @@ err: /* Close the file descriptor. */
static int
db_close(dbp, flags)
DB *dbp;
int flags;
u_int32_t flags;
{
DBC *dbc;
DB *tdbp;
@ -734,7 +759,7 @@ db_close(dbp, flags)
}
/* Sync the memory pool. */
if ((t_ret = memp_fsync(dbp->mpf)) != 0 &&
if (!LF_ISSET(DB_NOSYNC) && (t_ret = memp_fsync(dbp->mpf)) != 0 &&
t_ret != DB_INCOMPLETE && ret == 0)
ret = t_ret;
@ -796,18 +821,11 @@ db_fd(dbp, fdp)
DB *dbp;
int *fdp;
{
/* In-memory database can't have a file descriptor. */
if (F_ISSET(dbp, DB_AM_INMEM))
return (ENOENT);
/*
* XXX
* Truly spectacular layering violation. As we don't open the
* underlying file until we need it, it may not be initialized.
* Truly spectacular layering violation.
*/
if ((*fdp = dbp->mpf->fd) == -1)
return (ENOENT);
return (0);
return (__mp_xxx_fd(dbp->mpf, fdp));
}
/*
@ -821,6 +839,11 @@ __db_pgerr(dbp, pgno)
DB *dbp;
db_pgno_t pgno;
{
/*
* Three things are certain:
* Death, taxes, and lost data.
* Guess which has occurred.
*/
__db_err(dbp->dbenv,
"unable to create/retrieve page %lu", (u_long)pgno);
return (__db_panic(dbp));

View File

@ -1,11 +1,11 @@
/*-
* See the file LICENSE for redistribution information.
*
* Copyright (c) 1996, 1997
* Copyright (c) 1996, 1997, 1998
* Sleepycat Software. All rights reserved.
* @(#)db.src 10.4 (Sleepycat) 11/2/97
*
* @(#)db.src 10.6 (Sleepycat) 4/28/98
*/
#include "config.h"
PREFIX db
@ -153,4 +153,7 @@ END
* noop -- do nothing, but get an LSN.
*/
BEGIN noop
ARG fileid u_int32_t lu
ARG pgno db_pgno_t lu
POINTER prevlsn DB_LSN * lu
END

View File

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

View File

@ -1,7 +1,7 @@
/*-
* See the file LICENSE for redistribution information.
*
* Copyright (c) 1996, 1997
* Copyright (c) 1996, 1997, 1998
* Sleepycat Software. All rights reserved.
*/
/*
@ -44,7 +44,7 @@
#include "config.h"
#ifndef lint
static const char sccsid[] = "@(#)db_conv.c 10.8 (Sleepycat) 1/8/98";
static const char sccsid[] = "@(#)db_conv.c 10.13 (Sleepycat) 4/26/98";
#endif /* not lint */
#ifndef NO_SYSTEM_INCLUDES
@ -160,6 +160,13 @@ __db_convert(pg, pp, pagesize, pgin)
}
}
/*
* The offsets in the inp array are used to determine
* the size of entries on a page; therefore they
* cannot be converted until we've done all the
* entries.
*/
if (!pgin)
for (i = 0; i < NUM_ENT(h); i++)
M_16_SWAP(h->inp[i]);
@ -179,8 +186,8 @@ __db_convert(pg, pp, pagesize, pgin)
case B_DUPLICATE:
case B_OVERFLOW:
bo = (BOVERFLOW *)bk;
M_32_SWAP(bo->tlen);
M_32_SWAP(bo->pgno);
M_32_SWAP(bo->tlen);
break;
}
@ -194,17 +201,18 @@ __db_convert(pg, pp, pagesize, pgin)
M_16_SWAP(h->inp[i]);
bi = GET_BINTERNAL(h, i);
switch (B_TYPE(bi->type)) {
case B_KEYDATA:
M_16_SWAP(bi->len);
M_32_SWAP(bi->pgno);
M_32_SWAP(bi->nrecs);
switch (B_TYPE(bi->type)) {
case B_KEYDATA:
break;
case B_DUPLICATE:
case B_OVERFLOW:
bo = (BOVERFLOW *)bi;
M_32_SWAP(bo->tlen);
bo = (BOVERFLOW *)bi->data;
M_32_SWAP(bo->pgno);
M_32_SWAP(bo->tlen);
break;
}
@ -224,6 +232,7 @@ __db_convert(pg, pp, pagesize, pgin)
if (!pgin)
M_16_SWAP(h->inp[i]);
}
break;
case P_OVERFLOW:
case P_INVALID:
/* Nothing to do. */

View File

@ -1,7 +1,7 @@
/*-
* See the file LICENSE for redistribution information.
*
* Copyright (c) 1996, 1997
* Copyright (c) 1996, 1997, 1998
* Sleepycat Software. All rights reserved.
*/
/*
@ -43,14 +43,13 @@
#include "config.h"
#ifndef lint
static const char sccsid[] = "@(#)db_dispatch.c 10.9 (Sleepycat) 1/17/98";
static const char sccsid[] = "@(#)db_dispatch.c 10.14 (Sleepycat) 5/3/98";
#endif /* not lint */
#ifndef NO_SYSTEM_INCLUDES
#include <sys/types.h>
#include <errno.h>
#include <fcntl.h>
#include <stddef.h>
#include <stdlib.h>
#include <string.h>
@ -62,6 +61,7 @@ static const char sccsid[] = "@(#)db_dispatch.c 10.9 (Sleepycat) 1/17/98";
#include "db_am.h"
#include "common_ext.h"
#include "log_auto.h"
#include "txn_auto.h"
/*
* Data structures to manage the DB dispatch table. The dispatch table
@ -114,7 +114,7 @@ __db_dispatch(logp, db, lsnp, redo, info)
* seen it, then we call the appropriate recovery routine
* in "abort mode".
*/
if (rectype == DB_log_register ||
if (rectype == DB_log_register || rectype == DB_txn_ckp ||
__db_txnlist_find(info, txnid) == DB_NOTFOUND)
return ((dispatch_table[rectype])(logp,
db, lsnp, TXN_UNDO, info));
@ -124,7 +124,7 @@ __db_dispatch(logp, db, lsnp, redo, info)
* In the forward pass, if we haven't seen the transaction,
* do nothing, else recovery it.
*/
if (rectype == DB_log_register ||
if (rectype == DB_log_register || rectype == DB_txn_ckp ||
__db_txnlist_find(info, txnid) != DB_NOTFOUND)
return ((dispatch_table[rectype])(logp,
db, lsnp, TXN_REDO, info));
@ -188,14 +188,14 @@ int
__db_txnlist_init(retp)
void *retp;
{
__db_txnhead *headp;
DB_TXNHEAD *headp;
if ((headp = (struct __db_txnhead *)
__db_malloc(sizeof(struct __db_txnhead))) == NULL)
if ((headp = (DB_TXNHEAD *)__db_malloc(sizeof(DB_TXNHEAD))) == NULL)
return (ENOMEM);
LIST_INIT(&headp->head);
headp->maxid = 0;
headp->generation = 1;
*(void **)retp = headp;
return (0);
@ -212,25 +212,26 @@ __db_txnlist_add(listp, txnid)
void *listp;
u_int32_t txnid;
{
__db_txnhead *hp;
__db_txnlist *elp;
DB_TXNHEAD *hp;
DB_TXNLIST *elp;
if ((elp = (__db_txnlist *)__db_malloc(sizeof(__db_txnlist))) == NULL)
if ((elp = (DB_TXNLIST *)__db_malloc(sizeof(DB_TXNLIST))) == NULL)
return (ENOMEM);
elp->txnid = txnid;
hp = (struct __db_txnhead *)listp;
hp = (DB_TXNHEAD *)listp;
LIST_INSERT_HEAD(&hp->head, elp, links);
if (txnid > hp->maxid)
hp->maxid = txnid;
elp->generation = hp->generation;
return (0);
}
/*
* __db_txnlist_find --
* Checks to see if txnid is in the txnid list, returns 1 if found,
* 0 if not found.
* Checks to see if a txnid with the current generation is in the
* txnid list.
*
* PUBLIC: int __db_txnlist_find __P((void *, u_int32_t));
*/
@ -239,24 +240,65 @@ __db_txnlist_find(listp, txnid)
void *listp;
u_int32_t txnid;
{
__db_txnhead *hp;
__db_txnlist *p;
DB_TXNHEAD *hp;
DB_TXNLIST *p;
if ((hp = (struct __db_txnhead *)listp) == NULL)
if ((hp = (DB_TXNHEAD *)listp) == NULL)
return (DB_NOTFOUND);
if (hp->maxid < txnid) {
hp->maxid = txnid;
return (DB_NOTFOUND);
}
for (p = hp->head.lh_first; p != NULL; p = p->links.le_next)
if (p->txnid == txnid)
if (p->txnid == txnid && hp->generation == p->generation)
return (0);
return (DB_NOTFOUND);
}
/*
* __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
/*
* __db_txnlist_print --
@ -268,33 +310,14 @@ void
__db_txnlist_print(listp)
void *listp;
{
__db_txnhead *hp;
__db_txnlist *p;
DB_TXNHEAD *hp;
DB_TXNLIST *p;
hp = (struct __db_txnhead *)listp;
printf("Maxid: %lu\n", (u_long)hp->maxid);
hp = (DB_TXNHEAD *)listp;
printf("Maxid: %lu Generation: %lu\n", (u_long)hp->maxid,
(u_long)hp->generation);
for (p = hp->head.lh_first; p != NULL; p = p->links.le_next)
printf("TXNID: %lu\n", (u_long)p->txnid);
printf("TXNID: %lu(%lu)\n", (u_long)p->txnid,
(u_long)p->generation);
}
#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.
*
* Copyright (c) 1996, 1997
* Copyright (c) 1996, 1997, 1998
* Sleepycat Software. All rights reserved.
*/
#include "config.h"
#ifndef lint
static const char sccsid[] = "@(#)db_dup.c 10.11 (Sleepycat) 1/8/98";
static const char sccsid[] = "@(#)db_dup.c 10.18 (Sleepycat) 5/31/98";
#endif /* not lint */
#ifndef NO_SYSTEM_INCLUDES
#include <sys/types.h>
#include <sys/stat.h>
#include <errno.h>
#include <fcntl.h>
#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#endif
#include "db_int.h"
#include "db_page.h"
#include "db_swap.h"
#include "btree.h"
#include "db_am.h"
#include "common_ext.h"
static int __db_addpage __P((DB *,
PAGE **, db_indx_t *, int (*)(DB *, u_int32_t, PAGE **)));
@ -209,9 +201,8 @@ __db_dsplit(dbp, hp, indxp, size, newfunc)
PAGE *h, *np, *tp;
BKEYDATA *bk;
DBT page_dbt;
db_indx_t indx, nindex, oindex, sum;
db_indx_t halfbytes, i, lastsum;
int did_indx, ret, s;
db_indx_t halfbytes, i, indx, lastsum, nindex, oindex, s, sum;
int did_indx, ret;
h = *hp;
indx = *indxp;
@ -219,7 +210,7 @@ __db_dsplit(dbp, hp, indxp, size, newfunc)
/* Create a temporary page to do compaction onto. */
if ((tp = (PAGE *)__db_malloc(dbp->pgsize)) == NULL)
return (ENOMEM);
#ifdef DEBUG
#ifdef DIAGNOSTIC
memset(tp, 0xff, dbp->pgsize);
#endif
/* Create new page for the split. */
@ -239,6 +230,7 @@ __db_dsplit(dbp, hp, indxp, size, newfunc)
for (sum = 0, lastsum = 0, i = 0; i < NUM_ENT(h); i++) {
if (i == indx) {
sum += size;
did_indx = 1;
if (lastsum < halfbytes && sum >= halfbytes) {
/* We've crossed the halfway point. */
if ((db_indx_t)(halfbytes - lastsum) <
@ -252,7 +244,6 @@ __db_dsplit(dbp, hp, indxp, size, newfunc)
}
*indxp = i;
lastsum = sum;
did_indx = 1;
}
if (B_TYPE(GET_BKEYDATA(h, i)->type) == B_KEYDATA)
sum += BKEYDATA_SIZE(GET_BKEYDATA(h, i)->len);

View File

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

View File

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

View File

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

View File

@ -1,29 +1,26 @@
/*-
* See the file LICENSE for redistribution information.
*
* Copyright (c) 1996, 1997
* Copyright (c) 1996, 1997, 1998
* Sleepycat Software. All rights reserved.
*/
#include "config.h"
#ifndef lint
static const char sccsid[] = "@(#)db_ret.c 10.10 (Sleepycat) 11/28/97";
static const char sccsid[] = "@(#)db_ret.c 10.13 (Sleepycat) 5/7/98";
#endif /* not lint */
#ifndef NO_SYSTEM_INCLUDES
#include <sys/types.h>
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#endif
#include "db_int.h"
#include "db_page.h"
#include "btree.h"
#include "hash.h"
#include "db_am.h"
/*

View File

@ -1,27 +1,25 @@
/*-
* See the file LICENSE for redistribution information.
*
* Copyright (c) 1996, 1997
* Copyright (c) 1996, 1997, 1998
* Sleepycat Software. All rights reserved.
*/
#include "config.h"
#ifndef lint
static const char sccsid[] = "@(#)db_thread.c 8.13 (Sleepycat) 10/25/97";
static const char sccsid[] = "@(#)db_thread.c 8.15 (Sleepycat) 4/26/98";
#endif /* not lint */
#ifndef NO_SYSTEM_INCLUDES
#include <sys/types.h>
#include <errno.h>
#include <stdlib.h>
#include <string.h>
#endif
#include "db_int.h"
#include "db_page.h"
#include "shqueue.h"
#include "db_am.h"
static int __db_getlockid __P((DB *, DB *));

View File

@ -1,7 +1,7 @@
/*-
* See the file LICENSE for redistribution information.
*
* Copyright (c) 1996, 1997
* Copyright (c) 1996, 1997, 1998
* Sleepycat Software. All rights reserved.
*/
@ -9,9 +9,9 @@
#ifndef lint
static const char copyright[] =
"@(#) Copyright (c) 1997\n\
"@(#) Copyright (c) 1996, 1997, 1998\n\
Sleepycat Software Inc. All rights reserved.\n";
static const char sccsid[] = "@(#)db185.c 8.14 (Sleepycat) 10/25/97";
static const char sccsid[] = "@(#)db185.c 8.17 (Sleepycat) 5/7/98";
#endif
#ifndef NO_SYSTEM_INCLUDES
@ -20,7 +20,6 @@ static const char sccsid[] = "@(#)db185.c 8.14 (Sleepycat) 10/25/97";
#include <errno.h>
#include <fcntl.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#endif
@ -114,6 +113,16 @@ __dbopen(file, oflags, mode, type, openinfo)
* and DB 2.0 doesn't.
*
* !!!
* Setting the file name to NULL specifies that we're creating
* a temporary backing file, in DB 2.X. If we're opening the
* DB file read-only, change the flags to read-write, because
* temporary backing files cannot be opened read-only, and DB
* 2.X will return an error. We are cheating here -- if the
* application does a put on the database, it will succeed --
* although that would be a stupid thing for the application
* to do.
*
* !!!
* Note, the file name in DB 1.85 was a const -- we don't do
* that in DB 2.0, so do that cast.
*/
@ -122,6 +131,10 @@ __dbopen(file, oflags, mode, type, openinfo)
(void)__os_close(__os_open(file, oflags, mode));
dbinfop->re_source = (char *)file;
file = NULL;
if (O_RDONLY)
oflags &= ~O_RDONLY;
oflags |= O_RDWR;
}
if ((ri = openinfo) != NULL) {
@ -181,15 +194,14 @@ __dbopen(file, oflags, mode, type, openinfo)
* Store the returned pointer to the real DB 2.0 structure in the
* internal pointer. Ugly, but we're not going for pretty, here.
*/
if ((__set_errno(db_open(file,
type, __db_oflags(oflags), mode, NULL, dbinfop, &dbp))) != 0) {
if ((errno = db_open(file,
type, __db_oflags(oflags), mode, NULL, dbinfop, &dbp)) != 0) {
__db_free(db185p);
return (NULL);
}
/* Create the cursor used for sequential ops. */
if ((__set_errno(dbp->cursor(dbp, NULL, &((DB185 *)db185p)->dbc)))
!= 0) {
if ((errno = dbp->cursor(dbp, NULL, &((DB185 *)db185p)->dbc)) != 0) {
s_errno = errno;
(void)dbp->close(dbp, 0);
__db_free(db185p);

View File

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

View File

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

View File

@ -1,10 +1,10 @@
/*-
* See the file LICENSE for redistribution information.
*
* Copyright (c) 1996, 1997
* Copyright (c) 1996, 1997, 1998
* Sleepycat Software. All rights reserved.
*
* @(#)db_int.h.src 10.41 (Sleepycat) 1/8/98
* @(#)db_int.h.src 10.62 (Sleepycat) 5/23/98
*/
#ifndef _DB_INTERNAL_H_
@ -12,8 +12,6 @@
#include "db.h" /* Standard DB include file. */
#include "queue.h"
#include "os_func.h"
#include "os_ext.h"
/*******************************************************
* General purpose constants and macros.
@ -77,8 +75,8 @@
#define R_ADDR(base, offset) ((void *)((u_int8_t *)((base)->addr) + offset))
#define R_OFFSET(base, p) ((u_int8_t *)(p) - (u_int8_t *)(base)->addr)
/* Free and free-string macros that overwrite memory during debugging. */
#ifdef DEBUG
/* Free and free-string macros that overwrite memory. */
#ifdef DIAGNOSTIC
#undef FREE
#define FREE(p, len) { \
memset(p, 0xff, len); \
@ -117,36 +115,41 @@ typedef struct __fn {
#undef DB_LINE
#define DB_LINE "=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-="
/* Global variables. */
typedef struct __db_globals {
int db_mutexlocks; /* DB_MUTEXLOCKS */
int db_region_anon; /* DB_REGION_ANON, DB_REGION_NAME */
int db_region_init; /* DB_REGION_INIT */
int db_tsl_spins; /* DB_TSL_SPINS */
int db_pageyield; /* DB_PAGEYIELD */
} DB_GLOBALS;
extern DB_GLOBALS __db_global_values;
#define DB_GLOBAL(v) __db_global_values.v
/* Unused, or not-used-yet variable. "Shut that bloody compiler up!" */
#define COMPQUIET(n, v) (n) = (v)
/*
* Win16 needs specific syntax on callback functions. Nobody else cares.
*/
#ifndef DB_CALLBACK
#define DB_CALLBACK /* Nothing. */
#endif
/*******************************************************
* Files.
*******************************************************/
#ifndef MAXPATHLEN /* Maximum path length. */
#ifdef PATH_MAX
#define MAXPATHLEN PATH_MAX
#else
/*
* We use 1024 as the maximum path length. It's too hard to figure out what
* the real path length is, as it was traditionally stored in <sys/param.h>,
* and that file isn't always available.
*/
#undef MAXPATHLEN
#define MAXPATHLEN 1024
#endif
#endif
#define PATH_DOT "." /* Current working directory. */
#define PATH_SEPARATOR "/" /* Path separator character. */
#ifndef S_IRUSR /* UNIX specific file permissions. */
#define S_IRUSR 0000400 /* R for owner */
#define S_IWUSR 0000200 /* W for owner */
#define S_IRGRP 0000040 /* R for group */
#define S_IWGRP 0000020 /* W for group */
#define S_IROTH 0000004 /* R for other */
#define S_IWOTH 0000002 /* W for other */
#endif
#ifndef S_ISDIR /* UNIX specific: directory test. */
#define S_ISDIR(m) ((m & 0170000) == 0040000)
#endif
/*******************************************************
* Mutex support.
*******************************************************/
@ -176,12 +179,12 @@ typedef unsigned char tsl_t;
typedef struct _db_mutex_t {
#ifdef HAVE_SPINLOCKS
tsl_t tsl_resource; /* Resource test and set. */
#ifdef DEBUG
u_long pid; /* Lock holder: 0 or process pid. */
#ifdef DIAGNOSTIC
u_int32_t pid; /* Lock holder: 0 or process pid. */
#endif
#else
u_int32_t off; /* Backing file offset. */
u_long pid; /* Lock holder: 0 or process pid. */
u_int32_t pid; /* Lock holder: 0 or process pid. */
#endif
u_int32_t spins; /* Spins before block. */
u_int32_t mutex_set_wait; /* Granted after wait. */
@ -195,11 +198,11 @@ typedef struct _db_mutex_t {
*******************************************************/
/* Lock/unlock a DB thread. */
#define DB_THREAD_LOCK(dbp) \
(F_ISSET(dbp, DB_AM_THREAD) ? \
__db_mutex_lock((db_mutex_t *)(dbp)->mutexp, -1) : 0)
if (F_ISSET(dbp, DB_AM_THREAD)) \
(void)__db_mutex_lock((db_mutex_t *)(dbp)->mutexp, -1);
#define DB_THREAD_UNLOCK(dbp) \
(F_ISSET(dbp, DB_AM_THREAD) ? \
__db_mutex_unlock((db_mutex_t *)(dbp)->mutexp, -1) : 0)
if (F_ISSET(dbp, DB_AM_THREAD)) \
(void)__db_mutex_unlock((db_mutex_t *)(dbp)->mutexp, -1);
/* Btree/recno local statistics structure. */
struct __db_bt_lstat; typedef struct __db_bt_lstat DB_BTREE_LSTAT;
@ -228,7 +231,7 @@ typedef enum {
} APPNAME;
/*******************************************************
* Regions.
* Shared memory regions.
*******************************************************/
/*
* The shared memory regions share an initial structure so that the general
@ -240,16 +243,69 @@ typedef enum {
*/
typedef struct _rlayout {
db_mutex_t lock; /* Region mutex. */
#define DB_REGIONMAGIC 0x120897
u_int32_t valid; /* Valid magic number. */
u_int32_t refcnt; /* Region reference count. */
size_t size; /* Region length. */
int majver; /* Major version number. */
int minver; /* Minor version number. */
int patch; /* Patch version number. */
#define INVALID_SEGID -1
int segid; /* shmget(2) ID, or Win16 segment ID. */
#define DB_R_DELETED 0x01 /* Region was deleted. */
#define REGION_ANONYMOUS 0x01 /* Region is/should be in anon mem. */
u_int32_t flags;
} RLAYOUT;
/*
* DB creates all regions on 4K boundaries out of sheer paranoia, so that
* we don't make the underlying VM unhappy.
*/
#define DB_VMPAGESIZE (4 * 1024)
#define DB_ROUNDOFF(i) { \
(i) += DB_VMPAGESIZE - 1; \
(i) -= (i) % DB_VMPAGESIZE; \
}
/*
* The interface to region attach is nasty, there is a lot of complex stuff
* going on, which has to be retained between create/attach and detach. The
* REGINFO structure keeps track of it.
*/
struct __db_reginfo; typedef struct __db_reginfo REGINFO;
struct __db_reginfo {
/* Arguments. */
DB_ENV *dbenv; /* Region naming info. */
APPNAME appname; /* Region naming info. */
char *path; /* Region naming info. */
const char *file; /* Region naming info. */
int mode; /* Region mode, if a file. */
size_t size; /* Region size. */
u_int32_t dbflags; /* Region file open flags, if a file. */
/* Results. */
char *name; /* Region name. */
void *addr; /* Region address. */
int fd; /* Fcntl(2) locking file descriptor.
NB: this is only valid if a regular
file is backing the shared region,
and mmap(2) is being used to map it
into our address space. */
int segid; /* shmget(2) ID, or Win16 segment ID. */
/* Shared flags. */
/* 0x0001 COMMON MASK with RLAYOUT structure. */
#define REGION_CANGROW 0x0002 /* Can grow. */
#define REGION_CREATED 0x0004 /* Created. */
#define REGION_HOLDINGSYS 0x0008 /* Holding system resources. */
#define REGION_LASTDETACH 0x0010 /* Delete on last detach. */
#define REGION_MALLOC 0x0020 /* Created in malloc'd memory. */
#define REGION_PRIVATE 0x0040 /* Private to thread/process. */
#define REGION_REMOVED 0x0080 /* Already deleted. */
#define REGION_SIZEDEF 0x0100 /* Use default region size if exists. */
u_int32_t flags;
};
/*******************************************************
* Mpool.
*******************************************************/
@ -281,7 +337,7 @@ typedef struct __dbpginfo {
#define DB_LOGGING(dbp) \
(F_ISSET(dbp, DB_AM_LOGGING) && !F_ISSET(dbp, DB_AM_RECOVER))
#ifdef DEBUG
#ifdef DIAGNOSTIC
/*
* Debugging macro to log operations.
* If DEBUG_WOP is defined, log operations that modify the database.
@ -318,7 +374,7 @@ typedef struct __dbpginfo {
#else
#define DEBUG_LREAD(D, T, O, K, A, F)
#define DEBUG_LWRITE(D, T, O, K, A, F)
#endif /* DEBUG */
#endif /* DIAGNOSTIC */
/*******************************************************
* Transactions and recovery.
@ -339,4 +395,8 @@ struct __db_txn {
size_t off; /* Detail structure within region. */
TAILQ_ENTRY(__db_txn) links;
};
#include "os_func.h"
#include "os_ext.h"
#endif /* !_DB_INTERNAL_H_ */

View File

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

View File

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

View File

@ -1,7 +1,7 @@
/*-
* See the file LICENSE for redistribution information.
*
* Copyright (c) 1996, 1997
* Copyright (c) 1996, 1997, 1998
* Sleepycat Software. All rights reserved.
*/
/*
@ -43,11 +43,9 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* @(#)hash.src 10.2 (Sleepycat) 11/2/97
* @(#)hash.src 10.3 (Sleepycat) 4/10/98
*/
#include "config.h"
/*
* This is the source file used to create the logging functions for the
* hash package. Each access method (or set of routines wishing to register

View File

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

View File

@ -1,13 +1,13 @@
/*-
* See the file LICENSE for redistribution information.
*
* Copyright (c) 1996, 1997
* Copyright (c) 1996, 1997, 1998
* Sleepycat Software. All rights reserved.
*/
#include "config.h"
#ifndef lint
static const char sccsid[] = "@(#)hash_conv.c 10.4 (Sleepycat) 9/15/97";
static const char sccsid[] = "@(#)hash_conv.c 10.5 (Sleepycat) 4/10/98";
#endif /* not lint */
#ifndef NO_SYSTEM_INCLUDES

View File

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

View File

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

View File

@ -1,7 +1,7 @@
/*-
* See the file LICENSE for redistribution information.
*
* Copyright (c) 1996, 1997
* Copyright (c) 1996, 1997, 1998
* Sleepycat Software. All rights reserved.
*/
/*
@ -47,7 +47,7 @@
#include "config.h"
#ifndef lint
static const char sccsid[] = "@(#)hash_func.c 10.7 (Sleepycat) 9/16/97";
static const char sccsid[] = "@(#)hash_func.c 10.8 (Sleepycat) 4/10/98";
#endif /* not lint */
#ifndef NO_SYSTEM_INCLUDES

View File

@ -1,7 +1,7 @@
/*-
* See the file LICENSE for redistribution information.
*
* Copyright (c) 1996, 1997
* Copyright (c) 1996, 1997, 1998
* Sleepycat Software. All rights reserved.
*/
/*
@ -47,7 +47,7 @@
#include "config.h"
#ifndef lint
static const char sccsid[] = "@(#)hash_page.c 10.31 (Sleepycat) 1/8/98";
static const char sccsid[] = "@(#)hash_page.c 10.40 (Sleepycat) 6/2/98";
#endif /* not lint */
/*
@ -70,15 +70,11 @@ static const char sccsid[] = "@(#)hash_page.c 10.31 (Sleepycat) 1/8/98";
#include <sys/types.h>
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#endif
#include "db_int.h"
#include "db_page.h"
#include "db_swap.h"
#include "hash.h"
static int __ham_lock_bucket __P((DB *, HASH_CURSOR *, db_lockmode_t));
@ -266,6 +262,7 @@ __ham_item_last(hashp, cursorp, mode)
F_SET(cursorp, H_OK);
return (__ham_item_prev(hashp, cursorp, mode));
}
/*
* PUBLIC: int __ham_item_first __P((HTAB *, HASH_CURSOR *, db_lockmode_t));
*/
@ -285,8 +282,10 @@ __ham_item_first(hashp, cursorp, mode)
}
/*
* Returns a pointer to key/data pair on a page. In the case of bigkeys,
* just returns the page number and index of the bigkey pointer pair.
* __ham_item_prev --
* Returns a pointer to key/data pair on a page. In the case of
* bigkeys, just returns the page number and index of the bigkey
* pointer pair.
*
* PUBLIC: int __ham_item_prev __P((HTAB *, HASH_CURSOR *, db_lockmode_t));
*/
@ -487,12 +486,61 @@ __ham_putitem(p, dbt, type)
NUM_ENT(p) += 1;
}
/*
* PUBLIC: void __ham_reputpair
* PUBLIC: __P((PAGE *p, u_int32_t, u_int32_t, const DBT *, const DBT *));
*
* This is a special case to restore a key/data pair to its original
* location during recovery. We are guaranteed that the pair fits
* on the page and is not the last pair on the page (because if it's
* the last pair, the normal insert works).
*/
void
__ham_reputpair(p, psize, ndx, key, data)
PAGE *p;
u_int32_t psize, ndx;
const DBT *key, *data;
{
db_indx_t i, movebytes, newbytes;
u_int8_t *from;
/* First shuffle the existing items up on the page. */
movebytes =
(ndx == 0 ? psize : p->inp[H_DATAINDEX(ndx - 1)]) - HOFFSET(p);
newbytes = key->size + data->size;
from = (u_int8_t *)p + HOFFSET(p);
memmove(from - newbytes, from, movebytes);
/*
* Adjust the indices and move them up 2 spaces. Note that we
* have to check the exit condition inside the loop just in case
* we are dealing with index 0 (db_indx_t's are unsigned).
*/
for (i = NUM_ENT(p) - 1; ; i-- ) {
p->inp[i + 2] = p->inp[i] - newbytes;
if (i == H_KEYINDEX(ndx))
break;
}
/* Put the key and data on the page. */
p->inp[H_KEYINDEX(ndx)] =
(ndx == 0 ? psize : p->inp[H_DATAINDEX(ndx - 1)]) - key->size;
p->inp[H_DATAINDEX(ndx)] = p->inp[H_KEYINDEX(ndx)] - data->size;
memcpy(P_ENTRY(p, H_KEYINDEX(ndx)), key->data, key->size);
memcpy(P_ENTRY(p, H_DATAINDEX(ndx)), data->data, data->size);
/* Adjust page info. */
HOFFSET(p) -= newbytes;
NUM_ENT(p) += 2;
}
/*
* PUBLIC: int __ham_del_pair __P((HTAB *, HASH_CURSOR *, int));
* XXX TODO: if the item is an offdup, delete the other pages and
* then remove the pair. If the offpage page is 0, then you can
* just remove the pair.
*
* XXX
* TODO: if the item is an offdup, delete the other pages and then remove
* the pair. If the offpage page is 0, then you can just remove the pair.
*/
int
__ham_del_pair(hashp, cursorp, reclaim_page)
@ -648,8 +696,9 @@ __ham_del_pair(hashp, cursorp, reclaim_page)
/*
* Cursor is advanced to the beginning of the next page.
*/
cursorp->bndx = NDX_INVALID;
cursorp->bndx = 0;
cursorp->pgno = PGNO(p);
F_SET(cursorp, H_DELETED);
chg_pgno = PGNO(p);
if ((ret = __ham_dirty_page(hashp, p)) != 0 ||
(ret = __ham_del_page(hashp->dbp, n_pagep)) != 0)
@ -748,8 +797,8 @@ __ham_replpair(hashp, hcp, dbt, make_dup)
{
DBT old_dbt, tdata, tmp;
DB_LSN new_lsn;
int32_t change; /* XXX: Possible overflow. */
u_int32_t len;
int32_t change;
int is_big, ret, type;
u_int8_t *beg, *dest, *end, *hk, *src;
@ -789,7 +838,7 @@ __ham_replpair(hashp, hcp, dbt, make_dup)
change += dbt->doff + dbt->dlen - len;
if (change > (int)P_FREESPACE(hcp->pagep) || is_big) {
if (change > (int32_t)P_FREESPACE(hcp->pagep) || is_big) {
/*
* Case 3 -- two subcases.
* A. This is not really a partial operation, but an overwrite.
@ -954,7 +1003,7 @@ __ham_split_page(hashp, obucket, nbucket)
HTAB *hashp;
u_int32_t obucket, nbucket;
{
DBT key, val, page_dbt;
DBT key, page_dbt;
DB_ENV *dbenv;
DB_LSN new_lsn;
PAGE **pp, *old_pagep, *temp_pagep, *new_pagep;
@ -995,7 +1044,7 @@ __ham_split_page(hashp, obucket, nbucket)
big_len = 0;
big_buf = NULL;
val.flags = key.flags = 0;
key.flags = 0;
while (temp_pagep != NULL) {
for (n = 0; n < (db_indx_t)H_NUMPAIRS(temp_pagep); n++) {
if ((ret =
@ -1103,8 +1152,8 @@ __ham_split_page(hashp, obucket, nbucket)
ret == 0)
ret = tret;
err: if (0) {
if (old_pagep != NULL)
if (0) {
err: if (old_pagep != NULL)
(void)__ham_put_page(hashp->dbp, old_pagep, 1);
if (new_pagep != NULL)
(void)__ham_put_page(hashp->dbp, new_pagep, 1);
@ -1121,8 +1170,8 @@ err: if (0) {
* to which we just added something. This allows us to link overflow
* pages and return the new page having correctly put the last page.
*
* PUBLIC: int __ham_add_el __P((HTAB *, HASH_CURSOR *, const DBT *, const DBT *,
* PUBLIC: int));
* PUBLIC: int __ham_add_el
* PUBLIC: __P((HTAB *, HASH_CURSOR *, const DBT *, const DBT *, int));
*/
int
__ham_add_el(hashp, hcp, key, val, type)
@ -1136,8 +1185,8 @@ __ham_add_el(hashp, hcp, key, val, type)
DB_LSN new_lsn;
HOFFPAGE doff, koff;
db_pgno_t next_pgno;
u_int32_t data_size, key_size, pairsize;
int do_expand, is_keybig, is_databig, rectype, ret;
u_int32_t data_size, key_size, pairsize, rectype;
int do_expand, is_keybig, is_databig, ret;
int key_type, data_type;
do_expand = 0;
@ -1268,13 +1317,14 @@ __ham_add_el(hashp, hcp, key, val, type)
* another. Works for all types of hash entries (H_OFFPAGE, H_KEYDATA,
* H_DUPLICATE, H_OFFDUP). Since we log splits at a high level, we
* do not need to do any logging here.
* PUBLIC: void __ham_copy_item __P((HTAB *, PAGE *, int, PAGE *));
*
* PUBLIC: void __ham_copy_item __P((HTAB *, PAGE *, u_int32_t, PAGE *));
*/
void
__ham_copy_item(hashp, src_page, src_ndx, dest_page)
HTAB *hashp;
PAGE *src_page;
int src_ndx;
u_int32_t src_ndx;
PAGE *dest_page;
{
u_int32_t len;
@ -1409,7 +1459,7 @@ __ham_del_page(dbp, pagep)
LSN(pagep) = new_lsn;
}
#ifdef DEBUG
#ifdef DIAGNOSTIC
{
db_pgno_t __pgno;
DB_LSN __lsn;
@ -1563,13 +1613,13 @@ __ham_overflow_page(dbp, type, pp)
#ifdef DEBUG
/*
* PUBLIC: #ifdef DEBUG
* PUBLIC: int __bucket_to_page __P((HTAB *, int));
* PUBLIC: db_pgno_t __bucket_to_page __P((HTAB *, db_pgno_t));
* PUBLIC: #endif
*/
int
db_pgno_t
__bucket_to_page(hashp, n)
HTAB *hashp;
int n;
db_pgno_t n;
{
int ret_val;
@ -1580,7 +1630,6 @@ __bucket_to_page(hashp, n)
}
#endif
/*
* Create a bunch of overflow pages at the current split point.
* PUBLIC: void __ham_init_ovflpages __P((HTAB *));
@ -1660,8 +1709,9 @@ __ham_get_cpage(hashp, hcp, mode)
* Get a new page at the cursor, putting the last page if necessary.
* If the flag is set to H_ISDUP, then we are talking about the
* duplicate page, not the main page.
* PUBLIC: int __ham_next_cpage __P((HTAB *, HASH_CURSOR *, db_pgno_t,
* PUBLIC: int, int));
*
* PUBLIC: int __ham_next_cpage
* PUBLIC: __P((HTAB *, HASH_CURSOR *, db_pgno_t, int, u_int32_t));
*/
int
__ham_next_cpage(hashp, hcp, pgno, dirty, flags)
@ -1669,22 +1719,22 @@ __ham_next_cpage(hashp, hcp, pgno, dirty, flags)
HASH_CURSOR *hcp;
db_pgno_t pgno;
int dirty;
int flags;
u_int32_t flags;
{
PAGE *p;
int ret;
if (flags & H_ISDUP && hcp->dpagep != NULL &&
if (LF_ISSET(H_ISDUP) && hcp->dpagep != NULL &&
(ret = __ham_put_page(hashp->dbp, hcp->dpagep, dirty)) != 0)
return (ret);
else if (!(flags & H_ISDUP) && hcp->pagep != NULL &&
else if (!LF_ISSET(H_ISDUP) && hcp->pagep != NULL &&
(ret = __ham_put_page(hashp->dbp, hcp->pagep, dirty)) != 0)
return (ret);
if ((ret = __ham_get_page(hashp->dbp, pgno, &p)) != 0)
return (ret);
if (flags & H_ISDUP) {
if (LF_ISSET(H_ISDUP)) {
hcp->dpagep = p;
hcp->dpgno = pgno;
hcp->dndx = 0;

View File

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

View File

@ -1,14 +1,14 @@
/*-
* See the file LICENSE for redistribution information.
*
* Copyright (c) 1996, 1997
* Copyright (c) 1996, 1997, 1998
* Sleepycat Software. All rights reserved.
*/
#include "config.h"
#ifndef lint
static const char sccsid[] = "@(#)hash_stat.c 10.6 (Sleepycat) 7/2/97";
static const char sccsid[] = "@(#)hash_stat.c 10.8 (Sleepycat) 4/26/98";
#endif /* not lint */
#ifndef NO_SYSTEM_INCLUDES
@ -20,7 +20,6 @@ static const char sccsid[] = "@(#)hash_stat.c 10.6 (Sleepycat) 7/2/97";
#include "db_int.h"
#include "db_page.h"
#include "hash.h"
#include "common_ext.h"
/*
* __ham_stat --

View File

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

View File

@ -2,7 +2,7 @@
#ifndef _btree_ext_h_
#define _btree_ext_h_
int __bam_close __P((DB *));
int __bam_sync __P((DB *, int));
int __bam_sync __P((DB *, u_int32_t));
int __bam_cmp __P((DB *, const DBT *, EPG *));
int __bam_defcmp __P((const DBT *, const DBT *));
size_t __bam_defpfx __P((const DBT *, const DBT *));
@ -11,7 +11,7 @@ int __bam_pgout __P((db_pgno_t, void *, DBT *));
int __bam_mswap __P((PAGE *));
int __bam_cursor __P((DB *, DB_TXN *, DBC **));
int __bam_c_iclose __P((DB *, DBC *));
int __bam_get __P((DB *, DB_TXN *, DBT *, DBT *, int));
int __bam_get __P((DB *, DB_TXN *, DBT *, DBT *, u_int32_t));
int __bam_ovfl_chk __P((DB *, CURSOR *, u_int32_t, int));
int __bam_cprint __P((DB *));
int __bam_ca_delete __P((DB *, db_pgno_t, u_int32_t, CURSOR *, int));
@ -23,8 +23,8 @@ void __bam_ca_replace
__P((DB *, db_pgno_t, u_int32_t, ca_replace_arg));
void __bam_ca_split __P((DB *,
db_pgno_t, db_pgno_t, db_pgno_t, u_int32_t, int));
int __bam_delete __P((DB *, DB_TXN *, DBT *, int));
int __ram_delete __P((DB *, DB_TXN *, DBT *, int));
int __bam_delete __P((DB *, DB_TXN *, DBT *, u_int32_t));
int __ram_delete __P((DB *, DB_TXN *, DBT *, u_int32_t));
int __bam_ditem __P((DB *, PAGE *, u_int32_t));
int __bam_adjindx __P((DB *, PAGE *, u_int32_t, u_int32_t, int));
int __bam_dpage __P((DB *, const DBT *));
@ -35,10 +35,10 @@ int __bam_free __P((DB *, PAGE *));
int __bam_lt __P((DB *));
int __bam_lget __P((DB *, int, db_pgno_t, db_lockmode_t, DB_LOCK *));
int __bam_lput __P((DB *, DB_LOCK));
int __bam_pget __P((DB *, PAGE **, db_pgno_t *, int));
int __bam_put __P((DB *, DB_TXN *, DBT *, DBT *, int));
int __bam_pget __P((DB *, PAGE **, db_pgno_t *, u_int32_t));
int __bam_put __P((DB *, DB_TXN *, DBT *, DBT *, u_int32_t));
int __bam_iitem __P((DB *,
PAGE **, db_indx_t *, DBT *, DBT *, int, int));
PAGE **, db_indx_t *, DBT *, DBT *, u_int32_t, u_int32_t));
int __bam_ritem __P((DB *, PAGE *, u_int32_t, DBT *));
int __bam_pg_alloc_recover
__P((DB_LOG *, DBT *, DB_LSN *, int, void *));
@ -64,19 +64,19 @@ void __ram_ca __P((DB *, db_recno_t, ca_recno_arg));
int __ram_cprint __P((DB *));
int __ram_getno __P((DB *, const DBT *, db_recno_t *, int));
int __ram_snapshot __P((DB *));
int __bam_rsearch __P((DB *, db_recno_t *, u_int, int, int *));
int __bam_adjust __P((DB *, BTREE *, int));
int __bam_rsearch __P((DB *, db_recno_t *, u_int32_t, int, int *));
int __bam_adjust __P((DB *, BTREE *, int32_t));
int __bam_nrecs __P((DB *, db_recno_t *));
db_recno_t __bam_total __P((PAGE *));
int __bam_search __P((DB *,
const DBT *, u_int, int, db_recno_t *, int *));
const DBT *, u_int32_t, int, db_recno_t *, int *));
int __bam_stkrel __P((DB *));
int __bam_stkgrow __P((BTREE *));
int __bam_split __P((DB *, void *));
int __bam_broot __P((DB *, PAGE *, PAGE *, PAGE *));
int __ram_root __P((DB *, PAGE *, PAGE *, PAGE *));
int __bam_copy __P((DB *, PAGE *, PAGE *, u_int32_t, u_int32_t));
int __bam_stat __P((DB *, void *, void *(*)(size_t), int));
int __bam_stat __P((DB *, void *, void *(*)(size_t), u_int32_t));
void __bam_add_mstat __P((DB_BTREE_LSTAT *, DB_BTREE_LSTAT *));
int __bam_pg_alloc_log
__P((DB_LOG *, DB_TXN *, DB_LSN *, u_int32_t,

View File

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

View File

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

View File

@ -1,10 +1,10 @@
/*-
* See the file LICENSE for redistribution information.
*
* Copyright (c) 1997
* Copyright (c) 1997, 1998
* Sleepycat Software. All rights reserved.
*
* @(#)cxx_int.h 10.4 (Sleepycat) 8/22/97
* @(#)cxx_int.h 10.5 (Sleepycat) 4/10/98
*/
#ifndef _CXX_INT_H_

View File

@ -1,10 +1,10 @@
/*-
* See the file LICENSE for redistribution information.
*
* Copyright (c) 1996, 1997
* Copyright (c) 1996, 1997, 1998
* Sleepycat Software. All rights reserved.
*
* @(#)db.h.src 10.102 (Sleepycat) 1/18/98
* @(#)db.h.src 10.131 (Sleepycat) 6/2/98
*/
#ifndef _DB_H_
@ -54,8 +54,7 @@
*
* !!!
* We also provide the standard u_int, u_long etc., if they're not provided
* by the system. This isn't completely necessary, but the example programs
* need them.
* by the system.
*/
#ifndef __BIT_TYPES_DEFINED__
#define __BIT_TYPES_DEFINED__
@ -72,9 +71,9 @@
@u_long_decl@
#define DB_VERSION_MAJOR 2
#define DB_VERSION_MINOR 3
#define DB_VERSION_PATCH 16
#define DB_VERSION_STRING "Sleepycat Software: DB 2.3.16: (1/19/98)"
#define DB_VERSION_MINOR 4
#define DB_VERSION_PATCH 14
#define DB_VERSION_STRING "Sleepycat Software: DB 2.4.14: (6/2/98)"
typedef u_int32_t db_pgno_t; /* Page number type. */
typedef u_int16_t db_indx_t; /* Page offset type. */
@ -95,6 +94,7 @@ struct __db_bt_stat; typedef struct __db_bt_stat DB_BTREE_STAT;
struct __db_dbt; typedef struct __db_dbt DBT;
struct __db_env; typedef struct __db_env DB_ENV;
struct __db_info; typedef struct __db_info DB_INFO;
struct __db_lock_stat; typedef struct __db_lock_stat DB_LOCK_STAT;
struct __db_lockregion; typedef struct __db_lockregion DB_LOCKREGION;
struct __db_lockreq; typedef struct __db_lockreq DB_LOCKREQ;
struct __db_locktab; typedef struct __db_locktab DB_LOCKTAB;
@ -102,6 +102,7 @@ struct __db_log; typedef struct __db_log DB_LOG;
struct __db_log_stat; typedef struct __db_log_stat DB_LOG_STAT;
struct __db_lsn; typedef struct __db_lsn DB_LSN;
struct __db_mpool; typedef struct __db_mpool DB_MPOOL;
struct __db_mpool_finfo;typedef struct __db_mpool_finfo DB_MPOOL_FINFO;
struct __db_mpool_fstat;typedef struct __db_mpool_fstat DB_MPOOL_FSTAT;
struct __db_mpool_stat; typedef struct __db_mpool_stat DB_MPOOL_STAT;
struct __db_mpoolfile; typedef struct __db_mpoolfile DB_MPOOLFILE;
@ -134,7 +135,7 @@ struct __db_dbt {
* There are a set of functions that the application can replace with its
* own versions, and some other knobs which can be turned at run-time.
*/
#define DB_FUNC_CALLOC 1 /* ANSI C calloc. */
#define DB_FUNC_CALLOC 1 /* DELETED: ANSI C calloc. */
#define DB_FUNC_CLOSE 2 /* POSIX 1003.1 close. */
#define DB_FUNC_DIRFREE 3 /* DB: free directory list. */
#define DB_FUNC_DIRLIST 4 /* DB: create directory list. */
@ -149,12 +150,18 @@ struct __db_dbt {
#define DB_FUNC_REALLOC 13 /* ANSI C realloc. */
#define DB_FUNC_SEEK 14 /* POSIX 1003.1 lseek. */
#define DB_FUNC_SLEEP 15 /* DB: sleep secs/usecs. */
#define DB_FUNC_STRDUP 16 /* DB: strdup(3). */
#define DB_FUNC_STRDUP 16 /* DELETED: DB: strdup(3). */
#define DB_FUNC_UNLINK 17 /* POSIX 1003.1 unlink. */
#define DB_FUNC_UNMAP 18 /* DB: unmap shared memory file. */
#define DB_FUNC_WRITE 19 /* POSIX 1003.1 write. */
#define DB_FUNC_YIELD 20 /* DB: yield thread to scheduler. */
#define DB_TSL_SPINS 21 /* DB: initialize spin count. */
#define DB_FUNC_RUNLINK 22 /* DB: remove a shared region. */
#define DB_REGION_ANON 23 /* DB: anonymous, unnamed regions. */
#define DB_REGION_INIT 24 /* DB: page-fault regions in create. */
#define DB_REGION_NAME 25 /* DB: anonymous, named regions. */
#define DB_MUTEXLOCKS 26 /* DB: turn off all mutex locks. */
#define DB_PAGEYIELD 27 /* DB: yield the CPU on pool get. */
/*
* Database configuration and initialization.
@ -162,52 +169,51 @@ struct __db_dbt {
/*
* Flags understood by both db_open(3) and db_appinit(3).
*/
#define DB_CREATE 0x00001 /* O_CREAT: create file as necessary. */
#define DB_NOMMAP 0x00002 /* Don't mmap underlying file. */
#define DB_THREAD 0x00004 /* Free-thread DB package handles. */
#define DB_CREATE 0x000001 /* O_CREAT: create file as necessary. */
#define DB_NOMMAP 0x000002 /* Don't mmap underlying file. */
#define DB_THREAD 0x000004 /* Free-thread DB package handles. */
/*
* Flags understood by db_appinit(3).
*
* DB_MUTEXDEBUG is internal only, and not documented.
*/
/* 0x00007 COMMON MASK. */
#define DB_INIT_LOCK 0x00008 /* Initialize locking. */
#define DB_INIT_LOG 0x00010 /* Initialize logging. */
#define DB_INIT_MPOOL 0x00020 /* Initialize mpool. */
#define DB_INIT_TXN 0x00040 /* Initialize transactions. */
#define DB_MPOOL_PRIVATE 0x00080 /* Mpool: private memory pool. */
#define DB_MUTEXDEBUG 0x00100 /* Do not get/set mutexes in regions. */
#define DB_RECOVER 0x00200 /* Run normal recovery. */
#define DB_RECOVER_FATAL 0x00400 /* Run catastrophic recovery. */
#define DB_TXN_NOSYNC 0x00800 /* Do not sync log on commit. */
#define DB_USE_ENVIRON 0x01000 /* Use the environment. */
#define DB_USE_ENVIRON_ROOT 0x02000 /* Use the environment if root. */
/* 0x000007 COMMON MASK. */
#define DB_INIT_LOCK 0x000008 /* Initialize locking. */
#define DB_INIT_LOG 0x000010 /* Initialize logging. */
#define DB_INIT_MPOOL 0x000020 /* Initialize mpool. */
#define DB_INIT_TXN 0x000040 /* Initialize transactions. */
#define DB_MPOOL_PRIVATE 0x000080 /* Mpool: private memory pool. */
#define __UNUSED_100 0x000100
#define DB_RECOVER 0x000200 /* Run normal recovery. */
#define DB_RECOVER_FATAL 0x000400 /* Run catastrophic recovery. */
#define DB_TXN_NOSYNC 0x000800 /* Do not sync log on commit. */
#define DB_USE_ENVIRON 0x001000 /* Use the environment. */
#define DB_USE_ENVIRON_ROOT 0x002000 /* Use the environment if root. */
/* CURRENTLY UNUSED LOCK FLAGS. */
#define DB_TXN_LOCK_2PL 0x00000 /* Two-phase locking. */
#define DB_TXN_LOCK_OPTIMISTIC 0x00000 /* Optimistic locking. */
#define DB_TXN_LOCK_MASK 0x00000 /* Lock flags mask. */
#define DB_TXN_LOCK_2PL 0x000000 /* Two-phase locking. */
#define DB_TXN_LOCK_OPTIMIST 0x000000 /* Optimistic locking. */
#define DB_TXN_LOCK_MASK 0x000000 /* Lock flags mask. */
/* CURRENTLY UNUSED LOG FLAGS. */
#define DB_TXN_LOG_REDO 0x00000 /* Redo-only logging. */
#define DB_TXN_LOG_UNDO 0x00000 /* Undo-only logging. */
#define DB_TXN_LOG_UNDOREDO 0x00000 /* Undo/redo write-ahead logging. */
#define DB_TXN_LOG_MASK 0x00000 /* Log flags mask. */
#define DB_TXN_LOG_REDO 0x000000 /* Redo-only logging. */
#define DB_TXN_LOG_UNDO 0x000000 /* Undo-only logging. */
#define DB_TXN_LOG_UNDOREDO 0x000000 /* Undo/redo write-ahead logging. */
#define DB_TXN_LOG_MASK 0x000000 /* Log flags mask. */
/*
* Flags understood by db_open(3).
*
* DB_EXCL and DB_TEMPORARY are internal only, and not documented.
* DB_SEQUENTIAL is currently internal, but likely to be exported some day.
* DB_EXCL and DB_TEMPORARY are internal only, and are not documented.
* DB_SEQUENTIAL is currently internal, but may be exported some day.
*/
/* 0x00007 COMMON MASK. */
/* 0x07fff ALREADY USED. */
#define DB_EXCL 0x08000 /* O_EXCL: exclusive open. */
#define DB_RDONLY 0x10000 /* O_RDONLY: read-only. */
#define DB_SEQUENTIAL 0x20000 /* Indicate sequential access. */
#define DB_TEMPORARY 0x40000 /* Remove on last close. */
#define DB_TRUNCATE 0x80000 /* O_TRUNCATE: replace existing DB. */
/* 0x000007 COMMON MASK. */
/* 0x003fff ALREADY USED. */
#define __UNUSED_4000 0x004000
#define DB_EXCL 0x008000 /* O_EXCL: exclusive open. */
#define DB_RDONLY 0x010000 /* O_RDONLY: read-only. */
#define DB_SEQUENTIAL 0x020000 /* Indicate sequential access. */
#define DB_TEMPORARY 0x040000 /* Remove on last close. */
#define DB_TRUNCATE 0x080000 /* O_TRUNCATE: replace existing DB. */
/*
* Deadlock detector modes; used in the DBENV structure to configure the
@ -240,9 +246,9 @@ struct __db_env {
/* Locking. */
DB_LOCKTAB *lk_info; /* Return from lock_open(). */
u_int8_t *lk_conflicts; /* Two dimensional conflict matrix. */
int lk_modes; /* Number of lock modes in table. */
u_int lk_max; /* Maximum number of locks. */
u_int32_t lk_detect; /* Deadlock detect on every conflict. */
u_int32_t lk_modes; /* Number of lock modes in table. */
u_int32_t lk_max; /* Maximum number of locks. */
u_int32_t lk_detect; /* Deadlock detect on all conflicts. */
/* Logging. */
DB_LOG *lg_info; /* Return from log_open(). */
@ -255,7 +261,7 @@ struct __db_env {
/* Transactions. */
DB_TXNMGR *tx_info; /* Return from txn_open(). */
unsigned int tx_max; /* Maximum number of transactions. */
u_int32_t tx_max; /* Maximum number of transactions. */
int (*tx_recover) /* Dispatch function for recovery. */
__P((DB_LOG *, DBT *, DB_LSN *, int, void *));
@ -300,16 +306,16 @@ struct __db_info {
void *(*db_malloc) __P((size_t));
/* Btree access method. */
int bt_maxkey; /* Maximum keys per page. */
int bt_minkey; /* Minimum keys per page. */
u_int32_t bt_maxkey; /* Maximum keys per page. */
u_int32_t bt_minkey; /* Minimum keys per page. */
int (*bt_compare) /* Comparison function. */
__P((const DBT *, const DBT *));
size_t (*bt_prefix) /* Prefix function. */
__P((const DBT *, const DBT *));
/* Hash access method. */
unsigned int h_ffactor; /* Fill factor. */
unsigned int h_nelem; /* Number of elements. */
u_int32_t h_ffactor; /* Fill factor. */
u_int32_t h_nelem; /* Number of elements. */
u_int32_t (*h_hash) /* Hash function. */
__P((const void *, u_int32_t));
@ -353,6 +359,7 @@ struct __db_info {
#define DB_SET 0x010000 /* c_get(), log_get() */
#define DB_SET_RANGE 0x020000 /* c_get() */
#define DB_SET_RECNO 0x040000 /* c_get() */
#define DB_CURLSN 0x080000 /* log_put() */
/*
* DB (user visible) error return codes.
@ -435,14 +442,14 @@ struct __db {
void *(*db_malloc) __P((size_t));
/* Functions. */
int (*close) __P((DB *, int));
int (*close) __P((DB *, u_int32_t));
int (*cursor) __P((DB *, DB_TXN *, DBC **));
int (*del) __P((DB *, DB_TXN *, DBT *, int));
int (*del) __P((DB *, DB_TXN *, DBT *, u_int32_t));
int (*fd) __P((DB *, int *));
int (*get) __P((DB *, DB_TXN *, DBT *, DBT *, int));
int (*put) __P((DB *, DB_TXN *, DBT *, DBT *, int));
int (*stat) __P((DB *, void *, void *(*)(size_t), int));
int (*sync) __P((DB *, int));
int (*get) __P((DB *, DB_TXN *, DBT *, DBT *, u_int32_t));
int (*put) __P((DB *, DB_TXN *, DBT *, DBT *, u_int32_t));
int (*stat) __P((DB *, void *, void *(*)(size_t), u_int32_t));
int (*sync) __P((DB *, u_int32_t));
#define DB_AM_DUP 0x000001 /* DB_DUP (internal). */
#define DB_AM_INMEM 0x000002 /* In-memory; no sync on close. */
@ -483,9 +490,9 @@ struct __dbc {
void *internal; /* Access method private. */
int (*c_close) __P((DBC *));
int (*c_del) __P((DBC *, int));
int (*c_get) __P((DBC *, DBT *, DBT *, int));
int (*c_put) __P((DBC *, DBT *, DBT *, int));
int (*c_del) __P((DBC *, u_int32_t));
int (*c_get) __P((DBC *, DBT *, DBT *, u_int32_t));
int (*c_put) __P((DBC *, DBT *, DBT *, u_int32_t));
};
/* Btree/recno statistics structure. */
@ -524,10 +531,11 @@ struct __db_bt_stat {
#if defined(__cplusplus)
extern "C" {
#endif
int db_appinit __P((const char *, char * const *, DB_ENV *, int));
int db_appinit __P((const char *, char * const *, DB_ENV *, u_int32_t));
int db_appexit __P((DB_ENV *));
int db_jump_set __P((void *, int));
int db_open __P((const char *, DBTYPE, int, int, DB_ENV *, DB_INFO *, DB **));
int db_open __P((const char *,
DBTYPE, u_int32_t, int, DB_ENV *, DB_INFO *, DB **));
int db_value_set __P((int, int));
char *db_version __P((int *, int *, int *));
#if defined(__cplusplus)
@ -575,6 +583,21 @@ typedef enum {
DB_LOCK_IWR /* Intent to read and write. */
} db_lockmode_t;
/*
* Status of a lock.
*/
typedef enum {
DB_LSTAT_ABORTED, /* Lock belongs to an aborted txn. */
DB_LSTAT_ERR, /* Lock is bad. */
DB_LSTAT_FREE, /* Lock is unallocated. */
DB_LSTAT_HELD, /* Lock is currently held. */
DB_LSTAT_NOGRANT, /* Lock was not granted. */
DB_LSTAT_PENDING, /* Lock was waiting and has been
* promoted; waiting for the owner
* to run and upgrade it to held. */
DB_LSTAT_WAITING /* Lock is on the wait queue. */
} db_status_t;
/* Lock request structure. */
struct __db_lockreq {
db_lockop_t op; /* Operation. */
@ -596,19 +619,38 @@ extern const u_int8_t db_rw_conflicts[];
#define DB_LOCK_RIW_N 6
extern const u_int8_t db_riw_conflicts[];
struct __db_lock_stat {
u_int32_t st_magic; /* Lock file magic number. */
u_int32_t st_version; /* Lock file version number. */
u_int32_t st_maxlocks; /* Maximum number of locks in table. */
u_int32_t st_nmodes; /* Number of lock modes. */
u_int32_t st_numobjs; /* Number of objects. */
u_int32_t st_nlockers; /* Number of lockers. */
u_int32_t st_nconflicts; /* Number of lock conflicts. */
u_int32_t st_nrequests; /* Number of lock gets. */
u_int32_t st_nreleases; /* Number of lock puts. */
u_int32_t st_ndeadlocks; /* Number of lock deadlocks. */
u_int32_t st_region_wait; /* Region lock granted after wait. */
u_int32_t st_region_nowait; /* Region lock granted without wait. */
u_int32_t st_refcnt; /* Region reference count. */
u_int32_t st_regsize; /* Region size. */
};
#if defined(__cplusplus)
extern "C" {
#endif
int lock_close __P((DB_LOCKTAB *));
int lock_detect __P((DB_LOCKTAB *, int, int));
int lock_detect __P((DB_LOCKTAB *, u_int32_t, u_int32_t));
int lock_get __P((DB_LOCKTAB *,
u_int32_t, int, const DBT *, db_lockmode_t, DB_LOCK *));
u_int32_t, u_int32_t, const DBT *, db_lockmode_t, DB_LOCK *));
int lock_id __P((DB_LOCKTAB *, u_int32_t *));
int lock_open __P((const char *, int, int, DB_ENV *, DB_LOCKTAB **));
int lock_open __P((const char *,
u_int32_t, int, DB_ENV *, DB_LOCKTAB **));
int lock_put __P((DB_LOCKTAB *, DB_LOCK));
int lock_stat __P((DB_LOCKTAB *, DB_LOCK_STAT **, void *(*)(size_t)));
int lock_unlink __P((const char *, int, DB_ENV *));
int lock_vec __P((DB_LOCKTAB *,
u_int32_t, int, DB_LOCKREQ *, int, DB_LOCKREQ **));
u_int32_t, u_int32_t, DB_LOCKREQ *, int, DB_LOCKREQ **));
#if defined(__cplusplus)
}
#endif
@ -651,19 +693,21 @@ struct __db_log_stat {
u_int32_t st_region_nowait; /* Region lock granted without wait. */
u_int32_t st_cur_file; /* Current log file number. */
u_int32_t st_cur_offset; /* Current log file offset. */
u_int32_t st_refcnt; /* Region reference count. */
u_int32_t st_regsize; /* Region size. */
};
#if defined(__cplusplus)
extern "C" {
#endif
int log_archive __P((DB_LOG *, char **[], int, void *(*)(size_t)));
int log_archive __P((DB_LOG *, char **[], u_int32_t, void *(*)(size_t)));
int log_close __P((DB_LOG *));
int log_compare __P((const DB_LSN *, const DB_LSN *));
int log_file __P((DB_LOG *, const DB_LSN *, char *, size_t));
int log_flush __P((DB_LOG *, const DB_LSN *));
int log_get __P((DB_LOG *, DB_LSN *, DBT *, int));
int log_open __P((const char *, int, int, DB_ENV *, DB_LOG **));
int log_put __P((DB_LOG *, DB_LSN *, const DBT *, int));
int log_get __P((DB_LOG *, DB_LSN *, DBT *, u_int32_t));
int log_open __P((const char *, u_int32_t, int, DB_ENV *, DB_LOG **));
int log_put __P((DB_LOG *, DB_LSN *, const DBT *, u_int32_t));
int log_register __P((DB_LOG *, DB *, const char *, DBTYPE, u_int32_t *));
int log_stat __P((DB_LOG *, DB_LOG_STAT **, void *(*)(size_t)));
int log_unlink __P((const char *, int, DB_ENV *));
@ -705,6 +749,17 @@ struct __db_mpool_stat {
u_int32_t st_page_trickle; /* Pages written by memp_trickle. */
u_int32_t st_region_wait; /* Region lock granted after wait. */
u_int32_t st_region_nowait; /* Region lock granted without wait. */
u_int32_t st_refcnt; /* Region reference count. */
u_int32_t st_regsize; /* Region size. */
};
/* Mpool file open information structure. */
struct __db_mpool_finfo {
int ftype; /* File type. */
DBT *pgcookie; /* Byte-string passed to pgin/pgout. */
u_int8_t *fileid; /* Unique file ID. */
int32_t lsn_offset; /* LSN offset in page. */
u_int32_t clear_len; /* Cleared length on created pages. */
};
/* Mpool file statistics structure. */
@ -724,13 +779,13 @@ extern "C" {
#endif
int memp_close __P((DB_MPOOL *));
int memp_fclose __P((DB_MPOOLFILE *));
int memp_fget __P((DB_MPOOLFILE *, db_pgno_t *, int, void *));
int memp_fget __P((DB_MPOOLFILE *, db_pgno_t *, u_int32_t, void *));
int memp_fopen __P((DB_MPOOL *, const char *,
int, int, int, size_t, int, DBT *, u_int8_t *, DB_MPOOLFILE **));
int memp_fput __P((DB_MPOOLFILE *, void *, int));
int memp_fset __P((DB_MPOOLFILE *, void *, int));
u_int32_t, int, size_t, DB_MPOOL_FINFO *, DB_MPOOLFILE **));
int memp_fput __P((DB_MPOOLFILE *, void *, u_int32_t));
int memp_fset __P((DB_MPOOLFILE *, void *, u_int32_t));
int memp_fsync __P((DB_MPOOLFILE *));
int memp_open __P((const char *, int, int, DB_ENV *, DB_MPOOL **));
int memp_open __P((const char *, u_int32_t, int, DB_ENV *, DB_MPOOL **));
int memp_register __P((DB_MPOOL *, int,
int (*)(db_pgno_t, void *, DBT *),
int (*)(db_pgno_t, void *, DBT *)));
@ -774,7 +829,12 @@ struct __db_txn_stat {
u_int32_t st_nbegins; /* number of begun transactions */
u_int32_t st_ncommits; /* number of committed transactions */
u_int32_t st_nactive; /* number of active transactions */
DB_TXN_ACTIVE *st_txnarray; /* array of active transactions */
DB_TXN_ACTIVE
*st_txnarray; /* array of active transactions */
u_int32_t st_region_wait; /* Region lock granted after wait. */
u_int32_t st_region_nowait; /* Region lock granted without wait. */
u_int32_t st_refcnt; /* Region reference count. */
u_int32_t st_regsize; /* Region size. */
};
#if defined(__cplusplus)
@ -782,11 +842,11 @@ extern "C" {
#endif
int txn_abort __P((DB_TXN *));
int txn_begin __P((DB_TXNMGR *, DB_TXN *, DB_TXN **));
int txn_checkpoint __P((const DB_TXNMGR *, int, int));
int txn_checkpoint __P((const DB_TXNMGR *, u_int32_t, u_int32_t));
int txn_commit __P((DB_TXN *));
int txn_close __P((DB_TXNMGR *));
u_int32_t txn_id __P((DB_TXN *));
int txn_open __P((const char *, int, int, DB_ENV *, DB_TXNMGR **));
int txn_open __P((const char *, u_int32_t, int, DB_ENV *, DB_TXNMGR **));
int txn_prepare __P((DB_TXN *));
int txn_stat __P((DB_TXNMGR *, DB_TXN_STAT **, void *(*)(size_t)));
int txn_unlink __P((const char *, int, DB_ENV *));
@ -810,10 +870,17 @@ int txn_unlink __P((const char *, int, DB_ENV *));
*/
#define DBM_SUFFIX ".db"
#if defined(_XPG4_2)
typedef struct {
char *dptr;
size_t dsize;
} datum;
#else
typedef struct {
char *dptr;
int dsize;
} datum;
#endif
/*
* Translate DBM calls into DB calls so that DB doesn't step on the
@ -894,7 +961,7 @@ typedef enum {
typedef struct entry {
char *key;
void *data;
char *data;
} ENTRY;
/*
@ -909,7 +976,7 @@ typedef struct entry {
#if defined(__cplusplus)
extern "C" {
#endif
int __db_hcreate __P((unsigned int));
int __db_hcreate __P((size_t));
void __db_hdestroy __P((void));
ENTRY *__db_hsearch __P((ENTRY, ACTION));
#if defined(__cplusplus)

View File

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

View File

@ -1,10 +1,10 @@
/*-
* See the file LICENSE for redistribution information.
*
* Copyright (c) 1996, 1997
* Copyright (c) 1996, 1997, 1998
* Sleepycat Software. All rights reserved.
*
* @(#)db_am.h 10.8 (Sleepycat) 1/8/98
* @(#)db_am.h 10.9 (Sleepycat) 4/10/98
*/
#ifndef _DB_AM_H
#define _DB_AM_H

View File

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

View File

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

View File

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

View File

@ -53,7 +53,8 @@ int __db_debug_print
__P((DB_LOG *, DBT *, DB_LSN *, int, void *));
int __db_debug_read __P((void *, __db_debug_args **));
int __db_noop_log
__P((DB_LOG *, DB_TXN *, DB_LSN *, u_int32_t));
__P((DB_LOG *, DB_TXN *, DB_LSN *, u_int32_t,
u_int32_t, db_pgno_t, DB_LSN *));
int __db_noop_print
__P((DB_LOG *, DBT *, DB_LSN *, int, void *));
int __db_noop_read __P((void *, __db_noop_args **));
@ -67,8 +68,9 @@ int __db_add_recovery __P((DB_ENV *,
int __db_txnlist_init __P((void *));
int __db_txnlist_add __P((void *, u_int32_t));
int __db_txnlist_find __P((void *, u_int32_t));
void __db_txnlist_print __P((void *));
void __db_txnlist_end __P((void *));
void __db_txnlist_gen __P((void *, int));
void __db_txnlist_print __P((void *));
int __db_dput __P((DB *,
DBT *, PAGE **, db_indx_t *, int (*)(DB *, u_int32_t, PAGE **)));
int __db_drem __P((DB *,
@ -83,7 +85,7 @@ int __db_goff __P((DB *, DBT *,
u_int32_t, db_pgno_t, void **, u_int32_t *));
int __db_poff __P((DB *, const DBT *, db_pgno_t *,
int (*)(DB *, u_int32_t, PAGE **)));
int __db_ovref __P((DB *, db_pgno_t, int));
int __db_ovref __P((DB *, db_pgno_t, int32_t));
int __db_doff __P((DB *, db_pgno_t, int (*)(DB *, PAGE *)));
int __db_moff __P((DB *, const DBT *, db_pgno_t));
void __db_loadme __P((void));
@ -97,7 +99,8 @@ int __db_prnpage __P((DB_MPOOLFILE *, db_pgno_t));
int __db_prpage __P((PAGE *, int));
int __db_isbad __P((PAGE *, int));
void __db_pr __P((u_int8_t *, u_int32_t));
void __db_prflags __P((u_int32_t, const FN *));
int __db_prdbt __P((DBT *, int, FILE *));
void __db_prflags __P((u_int32_t, const FN *, FILE *));
int __db_addrem_recover
__P((DB_LOG *, DBT *, DB_LSN *, int, void *));
int __db_split_recover __P((DB_LOG *, DBT *, DB_LSN *, int, void *));
@ -108,8 +111,7 @@ int __db_relink_recover
int __db_addpage_recover
__P((DB_LOG *, DBT *, DB_LSN *, int, void *));
int __db_debug_recover __P((DB_LOG *, DBT *, DB_LSN *, int, void *));
int __db_noop_recover
__P((DB_LOG *, DBT *, DB_LSN *, int, void *));
int __db_noop_recover __P((DB_LOG *, DBT *, DB_LSN *, int, void *));
int __db_ret __P((DB *,
PAGE *, u_int32_t, DBT *, void **, u_int32_t *));
int __db_retcopy __P((DBT *,

View File

@ -1,10 +1,10 @@
/*-
* See the file LICENSE for redistribution information.
*
* Copyright (c) 1996, 1997
* Copyright (c) 1996, 1997, 1998
* Sleepycat Software. All rights reserved.
*
* @(#)db_int.h.src 10.41 (Sleepycat) 1/8/98
* @(#)db_int.h.src 10.62 (Sleepycat) 5/23/98
*/
#ifndef _DB_INTERNAL_H_
@ -12,8 +12,6 @@
#include "db.h" /* Standard DB include file. */
#include "queue.h"
#include "os_func.h"
#include "os_ext.h"
/*******************************************************
* General purpose constants and macros.
@ -77,8 +75,8 @@
#define R_ADDR(base, offset) ((void *)((u_int8_t *)((base)->addr) + offset))
#define R_OFFSET(base, p) ((u_int8_t *)(p) - (u_int8_t *)(base)->addr)
/* Free and free-string macros that overwrite memory during debugging. */
#ifdef DEBUG
/* Free and free-string macros that overwrite memory. */
#ifdef DIAGNOSTIC
#undef FREE
#define FREE(p, len) { \
memset(p, 0xff, len); \
@ -117,36 +115,41 @@ typedef struct __fn {
#undef DB_LINE
#define DB_LINE "=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-="
/* Global variables. */
typedef struct __db_globals {
int db_mutexlocks; /* DB_MUTEXLOCKS */
int db_region_anon; /* DB_REGION_ANON, DB_REGION_NAME */
int db_region_init; /* DB_REGION_INIT */
int db_tsl_spins; /* DB_TSL_SPINS */
int db_pageyield; /* DB_PAGEYIELD */
} DB_GLOBALS;
extern DB_GLOBALS __db_global_values;
#define DB_GLOBAL(v) __db_global_values.v
/* Unused, or not-used-yet variable. "Shut that bloody compiler up!" */
#define COMPQUIET(n, v) (n) = (v)
/*
* Win16 needs specific syntax on callback functions. Nobody else cares.
*/
#ifndef DB_CALLBACK
#define DB_CALLBACK /* Nothing. */
#endif
/*******************************************************
* Files.
*******************************************************/
#ifndef MAXPATHLEN /* Maximum path length. */
#ifdef PATH_MAX
#define MAXPATHLEN PATH_MAX
#else
/*
* We use 1024 as the maximum path length. It's too hard to figure out what
* the real path length is, as it was traditionally stored in <sys/param.h>,
* and that file isn't always available.
*/
#undef MAXPATHLEN
#define MAXPATHLEN 1024
#endif
#endif
#define PATH_DOT "." /* Current working directory. */
#define PATH_SEPARATOR "/" /* Path separator character. */
#ifndef S_IRUSR /* UNIX specific file permissions. */
#define S_IRUSR 0000400 /* R for owner */
#define S_IWUSR 0000200 /* W for owner */
#define S_IRGRP 0000040 /* R for group */
#define S_IWGRP 0000020 /* W for group */
#define S_IROTH 0000004 /* R for other */
#define S_IWOTH 0000002 /* W for other */
#endif
#ifndef S_ISDIR /* UNIX specific: directory test. */
#define S_ISDIR(m) ((m & 0170000) == 0040000)
#endif
/*******************************************************
* Mutex support.
*******************************************************/
@ -176,12 +179,12 @@ typedef struct __fn {
typedef struct _db_mutex_t {
#ifdef HAVE_SPINLOCKS
tsl_t tsl_resource; /* Resource test and set. */
#ifdef DEBUG
u_long pid; /* Lock holder: 0 or process pid. */
#ifdef DIAGNOSTIC
u_int32_t pid; /* Lock holder: 0 or process pid. */
#endif
#else
u_int32_t off; /* Backing file offset. */
u_long pid; /* Lock holder: 0 or process pid. */
u_int32_t pid; /* Lock holder: 0 or process pid. */
#endif
u_int32_t spins; /* Spins before block. */
u_int32_t mutex_set_wait; /* Granted after wait. */
@ -195,11 +198,11 @@ typedef struct _db_mutex_t {
*******************************************************/
/* Lock/unlock a DB thread. */
#define DB_THREAD_LOCK(dbp) \
(F_ISSET(dbp, DB_AM_THREAD) ? \
__db_mutex_lock((db_mutex_t *)(dbp)->mutexp, -1) : 0)
if (F_ISSET(dbp, DB_AM_THREAD)) \
(void)__db_mutex_lock((db_mutex_t *)(dbp)->mutexp, -1);
#define DB_THREAD_UNLOCK(dbp) \
(F_ISSET(dbp, DB_AM_THREAD) ? \
__db_mutex_unlock((db_mutex_t *)(dbp)->mutexp, -1) : 0)
if (F_ISSET(dbp, DB_AM_THREAD)) \
(void)__db_mutex_unlock((db_mutex_t *)(dbp)->mutexp, -1);
/* Btree/recno local statistics structure. */
struct __db_bt_lstat; typedef struct __db_bt_lstat DB_BTREE_LSTAT;
@ -228,7 +231,7 @@ typedef enum {
} APPNAME;
/*******************************************************
* Regions.
* Shared memory regions.
*******************************************************/
/*
* The shared memory regions share an initial structure so that the general
@ -240,16 +243,69 @@ typedef enum {
*/
typedef struct _rlayout {
db_mutex_t lock; /* Region mutex. */
#define DB_REGIONMAGIC 0x120897
u_int32_t valid; /* Valid magic number. */
u_int32_t refcnt; /* Region reference count. */
size_t size; /* Region length. */
int majver; /* Major version number. */
int minver; /* Minor version number. */
int patch; /* Patch version number. */
#define INVALID_SEGID -1
int segid; /* shmget(2) ID, or Win16 segment ID. */
#define DB_R_DELETED 0x01 /* Region was deleted. */
#define REGION_ANONYMOUS 0x01 /* Region is/should be in anon mem. */
u_int32_t flags;
} RLAYOUT;
/*
* DB creates all regions on 4K boundaries out of sheer paranoia, so that
* we don't make the underlying VM unhappy.
*/
#define DB_VMPAGESIZE (4 * 1024)
#define DB_ROUNDOFF(i) { \
(i) += DB_VMPAGESIZE - 1; \
(i) -= (i) % DB_VMPAGESIZE; \
}
/*
* The interface to region attach is nasty, there is a lot of complex stuff
* going on, which has to be retained between create/attach and detach. The
* REGINFO structure keeps track of it.
*/
struct __db_reginfo; typedef struct __db_reginfo REGINFO;
struct __db_reginfo {
/* Arguments. */
DB_ENV *dbenv; /* Region naming info. */
APPNAME appname; /* Region naming info. */
char *path; /* Region naming info. */
const char *file; /* Region naming info. */
int mode; /* Region mode, if a file. */
size_t size; /* Region size. */
u_int32_t dbflags; /* Region file open flags, if a file. */
/* Results. */
char *name; /* Region name. */
void *addr; /* Region address. */
int fd; /* Fcntl(2) locking file descriptor.
NB: this is only valid if a regular
file is backing the shared region,
and mmap(2) is being used to map it
into our address space. */
int segid; /* shmget(2) ID, or Win16 segment ID. */
/* Shared flags. */
/* 0x0001 COMMON MASK with RLAYOUT structure. */
#define REGION_CANGROW 0x0002 /* Can grow. */
#define REGION_CREATED 0x0004 /* Created. */
#define REGION_HOLDINGSYS 0x0008 /* Holding system resources. */
#define REGION_LASTDETACH 0x0010 /* Delete on last detach. */
#define REGION_MALLOC 0x0020 /* Created in malloc'd memory. */
#define REGION_PRIVATE 0x0040 /* Private to thread/process. */
#define REGION_REMOVED 0x0080 /* Already deleted. */
#define REGION_SIZEDEF 0x0100 /* Use default region size if exists. */
u_int32_t flags;
};
/*******************************************************
* Mpool.
*******************************************************/
@ -281,7 +337,7 @@ typedef struct __dbpginfo {
#define DB_LOGGING(dbp) \
(F_ISSET(dbp, DB_AM_LOGGING) && !F_ISSET(dbp, DB_AM_RECOVER))
#ifdef DEBUG
#ifdef DIAGNOSTIC
/*
* Debugging macro to log operations.
* If DEBUG_WOP is defined, log operations that modify the database.
@ -318,7 +374,7 @@ typedef struct __dbpginfo {
#else
#define DEBUG_LREAD(D, T, O, K, A, F)
#define DEBUG_LWRITE(D, T, O, K, A, F)
#endif /* DEBUG */
#endif /* DIAGNOSTIC */
/*******************************************************
* Transactions and recovery.
@ -339,4 +395,8 @@ struct __db_txn {
size_t off; /* Detail structure within region. */
TAILQ_ENTRY(__db_txn) links;
};
#include "os_func.h"
#include "os_ext.h"
#endif /* !_DB_INTERNAL_H_ */

View File

@ -1,10 +1,10 @@
/*-
* See the file LICENSE for redistribution information.
*
* Copyright (c) 1996, 1997
* Copyright (c) 1996, 1997, 1998
* Sleepycat Software. All rights reserved.
*
* @(#)db_page.h 10.13 (Sleepycat) 9/24/97
* @(#)db_page.h 10.15 (Sleepycat) 5/1/98
*/
#ifndef _DB_PAGE_H_
@ -29,6 +29,14 @@
#define PGNO_INVALID 0 /* Metadata page number, therefore illegal. */
#define PGNO_ROOT 1 /* Root is page #1. */
/*
* When we create pages in mpool, we ask mpool to clear some number of bytes
* in the header. This number must be at least as big as the regular page
* headers and cover enough of the btree and hash meta-data pages to obliterate
* the magic and version numbers.
*/
#define DB_PAGE_CLEAR_LEN 32
/************************************************************************
BTREE METADATA PAGE LAYOUT
************************************************************************/

View File

@ -1,10 +1,10 @@
/*-
* See the file LICENSE for redistribution information.
*
* Copyright (c) 1996, 1997
* Copyright (c) 1996, 1997, 1998
* Sleepycat Software. All rights reserved.
*
* @(#)db_shash.h 10.2 (Sleepycat) 9/16/97
* @(#)db_shash.h 10.3 (Sleepycat) 4/10/98
*/
/* Hash Headers */

View File

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

View File

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

View File

@ -75,7 +75,7 @@ int __ham_mswap __P((void *));
#ifdef DEBUG
void __ham_dump_bucket __P((HTAB *, u_int32_t));
#endif
int __ham_add_dup __P((HTAB *, HASH_CURSOR *, DBT *, int));
int __ham_add_dup __P((HTAB *, HASH_CURSOR *, DBT *, u_int32_t));
void __ham_move_offpage __P((HTAB *, PAGE *, u_int32_t, db_pgno_t));
u_int32_t __ham_func2 __P((const void *, u_int32_t));
u_int32_t __ham_func3 __P((const void *, u_int32_t));
@ -90,14 +90,16 @@ int __ham_item_first __P((HTAB *, HASH_CURSOR *, db_lockmode_t));
int __ham_item_prev __P((HTAB *, HASH_CURSOR *, db_lockmode_t));
int __ham_item_next __P((HTAB *, HASH_CURSOR *, db_lockmode_t));
void __ham_putitem __P((PAGE *p, const DBT *, int));
void __ham_reputpair
__P((PAGE *p, u_int32_t, u_int32_t, const DBT *, const DBT *));
int __ham_del_pair __P((HTAB *, HASH_CURSOR *, int));
int __ham_replpair __P((HTAB *, HASH_CURSOR *, DBT *, u_int32_t));
void __ham_onpage_replace __P((PAGE *, size_t, u_int32_t, int32_t,
int32_t, DBT *));
int __ham_split_page __P((HTAB *, u_int32_t, u_int32_t));
int __ham_add_el __P((HTAB *, HASH_CURSOR *, const DBT *, const DBT *,
int));
void __ham_copy_item __P((HTAB *, PAGE *, int, PAGE *));
int __ham_add_el
__P((HTAB *, HASH_CURSOR *, const DBT *, const DBT *, int));
void __ham_copy_item __P((HTAB *, PAGE *, u_int32_t, PAGE *));
int __ham_add_ovflpage __P((HTAB *, PAGE *, int, PAGE **));
int __ham_new_page __P((HTAB *, u_int32_t, u_int32_t, PAGE **));
int __ham_del_page __P((DB *, PAGE *));
@ -106,12 +108,12 @@ int __ham_dirty_page __P((HTAB *, PAGE *));
int __ham_get_page __P((DB *, db_pgno_t, PAGE **));
int __ham_overflow_page __P((DB *, u_int32_t, PAGE **));
#ifdef DEBUG
int __bucket_to_page __P((HTAB *, int));
db_pgno_t __bucket_to_page __P((HTAB *, db_pgno_t));
#endif
void __ham_init_ovflpages __P((HTAB *));
int __ham_get_cpage __P((HTAB *, HASH_CURSOR *, db_lockmode_t));
int __ham_next_cpage __P((HTAB *, HASH_CURSOR *, db_pgno_t,
int, int));
int __ham_next_cpage
__P((HTAB *, HASH_CURSOR *, db_pgno_t, int, u_int32_t));
void __ham_dpair __P((DB *, PAGE *, u_int32_t));
int __ham_insdel_recover
__P((DB_LOG *, DBT *, DB_LSN *, int, void *));

View File

@ -1,16 +1,19 @@
/*-
* See the file LICENSE for redistribution information.
*
* Copyright (c) 1996, 1997
* Copyright (c) 1996, 1997, 1998
* Sleepycat Software. All rights reserved.
*
* @(#)lock.h 10.10 (Sleepycat) 11/13/97
* @(#)lock.h 10.15 (Sleepycat) 5/10/98
*/
typedef struct __db_lockobj DB_LOCKOBJ;
#define DB_DEFAULT_LOCK_FILE "__db_lock.share"
#define DB_LOCK_DEFAULT_N 5000
#ifndef DB_LOCK_DEFAULT_N
#define DB_LOCK_DEFAULT_N 5000 /* Default # of locks in region. */
#endif
/*
* The locker id space is divided between the transaction manager and the lock
@ -54,9 +57,9 @@ struct __db_lockregion {
/* Macros to lock/unlock the region. */
#define LOCK_LOCKREGION(lt) \
(void)__db_mutex_lock(&(lt)->region->hdr.lock, (lt)->fd)
(void)__db_mutex_lock(&(lt)->region->hdr.lock, (lt)->reginfo.fd)
#define UNLOCK_LOCKREGION(lt) \
(void)__db_mutex_unlock(&(lt)->region->hdr.lock, (lt)->fd)
(void)__db_mutex_unlock(&(lt)->region->hdr.lock, (lt)->reginfo.fd)
/*
* Since we will be keeping DBTs in shared memory, we need the equivalent
@ -69,9 +72,6 @@ typedef struct __sh_dbt {
#define SH_DBT_PTR(p) ((void *)(((u_int8_t *)(p)) + (p)->off))
/*
* The lock table is the per-process cookie returned from a lock_open call.
*/
struct __db_lockobj {
SH_DBT lockobj; /* Identifies object locked. */
SH_TAILQ_ENTRY links; /* Links for free list. */
@ -98,12 +98,14 @@ struct __db_lockobj {
#define holders dlinks._holders
#define heldby dlinks._heldby
/*
* The lock table is the per-process cookie returned from a lock_open call.
*/
struct __db_locktab {
DB_ENV *dbenv; /* Environment. */
int fd; /* mapped file descriptor */
DB_LOCKREGION *region; /* address of shared memory region */
REGINFO reginfo; /* Region information. */
DB_LOCKREGION *region; /* Address of shared memory region. */
DB_HASHTAB *hashtab; /* Beginning of hash table. */
size_t reg_size; /* last known size of lock region */
void *mem; /* Beginning of string space. */
u_int8_t *conflicts; /* Pointer to conflict matrix. */
};
@ -112,21 +114,6 @@ struct __db_locktab {
#define CONFLICTS(T, HELD, 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
* is running low when we need to grow the region.
@ -187,17 +174,4 @@ struct __db_lock {
ALIGN((N) * sizeof(DB_LOCKOBJ), sizeof(size_t)) + \
ALIGN(STRING_SIZE(N), sizeof(size_t)))
#ifdef DEBUG
#define LOCK_DEBUG_LOCKERS 0x0001
#define LOCK_DEBUG_LOCK 0x0002
#define LOCK_DEBUG_OBJ 0x0004
#define LOCK_DEBUG_CONF 0x0008
#define LOCK_DEBUG_MEM 0x0010
#define LOCK_DEBUG_BUCKET 0x0020
#define LOCK_DEBUG_OBJECTS 0x0040
#define LOCK_DEBUG_ALL 0xFFFF
#define LOCK_DEBUG_NOMUTEX 0x0100
#endif
#include "lock_ext.h"

View File

@ -1,14 +1,17 @@
/* DO NOT EDIT: automatically built by dist/distrib. */
#ifndef _lock_ext_h_
#define _lock_ext_h_
void __lock_dump_region __P((DB_LOCKTAB *, u_int));
int __lock_is_locked
__P((DB_LOCKTAB *, u_int32_t, DBT *, db_lockmode_t));
void __lock_printlock __P((DB_LOCKTAB *, struct __db_lock *, int));
int __lock_getobj __P((DB_LOCKTAB *,
u_int32_t, const DBT *, u_int32_t type, DB_LOCKOBJ **));
int __lock_validate_region __P((DB_LOCKTAB *));
int __lock_grow_region __P((DB_LOCKTAB *, int, size_t));
void __lock_dump_region __P((DB_LOCKTAB *, char *, FILE *));
int __lock_cmp __P((const DBT *, DB_LOCKOBJ *));
int __lock_locker_cmp __P((u_int32_t, DB_LOCKOBJ *));
int __lock_ohash __P((const DBT *));
u_int32_t __lock_locker_hash __P((u_int32_t));
u_int32_t __lock_ohash __P((const DBT *));
u_int32_t __lock_lhash __P((DB_LOCKOBJ *));
u_int32_t __lock_locker_hash __P((u_int32_t));
#endif /* _lock_ext_h_ */

View File

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

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_recover __P((DB_ENV *));
int __log_findckp __P((DB_LOG *, DB_LSN *));
int __log_get __P((DB_LOG *, DB_LSN *, DBT *, int, int));
int __log_put __P((DB_LOG *, DB_LSN *, const DBT *, int));
int __log_get __P((DB_LOG *, DB_LSN *, DBT *, u_int32_t, int));
int __log_put __P((DB_LOG *, DB_LSN *, const DBT *, u_int32_t));
int __log_name __P((DB_LOG *, int, char **));
int __log_register_recover
__P((DB_LOG *, DBT *, DB_LSN *, int, void *));

View File

@ -1,10 +1,10 @@
/*-
* See the file LICENSE for redistribution information.
*
* Copyright (c) 1996, 1997
* Copyright (c) 1996, 1997, 1998
* Sleepycat Software. All rights reserved.
*
* @(#)mp.h 10.25 (Sleepycat) 1/8/98
* @(#)mp.h 10.33 (Sleepycat) 5/4/98
*/
struct __bh; typedef struct __bh BH;
@ -19,7 +19,9 @@ struct __mpoolfile; typedef struct __mpoolfile MPOOLFILE;
* We default to 128K (16 8K pages) if the user doesn't specify, and
* require a minimum of 20K.
*/
#ifndef DB_CACHESIZE_DEF
#define DB_CACHESIZE_DEF (128 * 1024)
#endif
#define DB_CACHESIZE_MIN ( 20 * 1024)
#define INVALID 0 /* Invalid shared memory offset. */
@ -79,30 +81,30 @@ struct __mpoolfile; typedef struct __mpoolfile MPOOLFILE;
#define LOCKINIT(dbmp, mutexp) \
if (F_ISSET(dbmp, MP_LOCKHANDLE | MP_LOCKREGION)) \
(void)__db_mutex_init(mutexp, \
MUTEX_LOCK_OFFSET((dbmp)->maddr, mutexp))
MUTEX_LOCK_OFFSET((dbmp)->reginfo.addr, mutexp))
#define LOCKHANDLE(dbmp, mutexp) \
if (F_ISSET(dbmp, MP_LOCKHANDLE)) \
(void)__db_mutex_lock(mutexp, (dbmp)->fd)
(void)__db_mutex_lock(mutexp, (dbmp)->reginfo.fd)
#define UNLOCKHANDLE(dbmp, mutexp) \
if (F_ISSET(dbmp, MP_LOCKHANDLE)) \
(void)__db_mutex_unlock(mutexp, (dbmp)->fd)
(void)__db_mutex_unlock(mutexp, (dbmp)->reginfo.fd)
#define LOCKREGION(dbmp) \
if (F_ISSET(dbmp, MP_LOCKREGION)) \
(void)__db_mutex_lock(&((RLAYOUT *)(dbmp)->mp)->lock, \
(dbmp)->fd)
(dbmp)->reginfo.fd)
#define UNLOCKREGION(dbmp) \
if (F_ISSET(dbmp, MP_LOCKREGION)) \
(void)__db_mutex_unlock(&((RLAYOUT *)(dbmp)->mp)->lock, \
(dbmp)->fd)
(dbmp)->reginfo.fd)
#define LOCKBUFFER(dbmp, bhp) \
if (F_ISSET(dbmp, MP_LOCKREGION)) \
(void)__db_mutex_lock(&(bhp)->mutex, (dbmp)->fd)
(void)__db_mutex_lock(&(bhp)->mutex, (dbmp)->reginfo.fd)
#define UNLOCKBUFFER(dbmp, bhp) \
if (F_ISSET(dbmp, MP_LOCKREGION)) \
(void)__db_mutex_unlock(&(bhp)->mutex, (dbmp)->fd)
(void)__db_mutex_unlock(&(bhp)->mutex, (dbmp)->reginfo.fd)
/*
* DB_MPOOL --
@ -120,20 +122,16 @@ struct __db_mpool {
/* These fields are not protected. */
DB_ENV *dbenv; /* Reference to error information. */
REGINFO reginfo; /* Region information. */
MPOOL *mp; /* Address of the shared MPOOL. */
void *maddr; /* Address of mmap'd region. */
void *addr; /* Address of shalloc() region. */
DB_HASHTAB *htab; /* Hash table of bucket headers. */
int fd; /* Underlying mmap'd fd. */
#define MP_ISPRIVATE 0x01 /* Private, so local memory. */
#define MP_LOCKHANDLE 0x02 /* Threaded, lock handles and region. */
#define MP_LOCKREGION 0x04 /* Concurrent access, lock region. */
#define MP_MALLOC 0x08 /* If region in allocated memory. */
#define MP_LOCKHANDLE 0x01 /* Threaded, lock handles and region. */
#define MP_LOCKREGION 0x02 /* Concurrent access, lock region. */
u_int32_t flags;
};
@ -146,8 +144,8 @@ struct __db_mpreg {
int ftype; /* File type. */
/* Pgin, pgout routines. */
int (*pgin) __P((db_pgno_t, void *, DBT *));
int (*pgout) __P((db_pgno_t, void *, DBT *));
int (DB_CALLBACK *pgin) __P((db_pgno_t, void *, DBT *));
int (DB_CALLBACK *pgout) __P((db_pgno_t, void *, DBT *));
};
/*
@ -207,7 +205,7 @@ struct __mpool {
size_t htab_buckets; /* Number of hash table entries. */
DB_LSN lsn; /* Maximum checkpoint LSN. */
int lsn_cnt; /* Checkpoint buffers left to write. */
u_int32_t lsn_cnt; /* Checkpoint buffers left to write. */
DB_MPOOL_STAT stat; /* Global mpool statistics. */
@ -225,7 +223,9 @@ struct __mpoolfile {
u_int32_t ref; /* Reference count. */
int ftype; /* File type. */
int lsn_off; /* Page's LSN offset. */
int32_t lsn_off; /* Page's LSN offset. */
u_int32_t clear_len; /* Bytes to clear on page create. */
size_t path_off; /* File name location. */
size_t fileid_off; /* File identification location. */
@ -233,9 +233,10 @@ struct __mpoolfile {
size_t pgcookie_len; /* Pgin/pgout cookie length. */
size_t pgcookie_off; /* Pgin/pgout cookie location. */
int lsn_cnt; /* Checkpoint buffers left to write. */
u_int32_t lsn_cnt; /* Checkpoint buffers left to write. */
db_pgno_t last_pgno; /* Last page in the file. */
db_pgno_t orig_last_pgno; /* Original last page in the file. */
#define MP_CAN_MMAP 0x01 /* If the file can be mmap'd. */
#define MP_TEMP 0x02 /* Backing file is a temporary. */

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_pg __P((DB_MPOOLFILE *, BH *, int));
void __memp_bhfree __P((DB_MPOOL *, MPOOLFILE *, BH *, int));
int __memp_fopen __P((DB_MPOOL *, MPOOLFILE *, const char *, int,
int, int, size_t, int, DBT *, u_int8_t *, int, DB_MPOOLFILE **));
int __memp_fopen __P((DB_MPOOL *, MPOOLFILE *, const char *,
u_int32_t, int, size_t, int, DB_MPOOL_FINFO *, DB_MPOOLFILE **));
char * __memp_fn __P((DB_MPOOLFILE *));
char * __memp_fns __P((DB_MPOOL *, MPOOLFILE *));
void __memp_debug __P((DB_MPOOL *, FILE *, int));
void __memp_dump_region __P((DB_MPOOL *, char *, FILE *));
int __memp_ralloc __P((DB_MPOOL *, size_t, size_t *, void *));
int __memp_ropen
__P((DB_MPOOL *, const char *, size_t, int, int));
int __memp_rclose __P((DB_MPOOL *));
__P((DB_MPOOL *, const char *, size_t, int, int, u_int32_t));
int __mp_xxx_fd __P((DB_MPOOLFILE *, int *));
#endif /* _mp_ext_h_ */

View File

@ -1,7 +1,7 @@
/* DO NOT EDIT: automatically built by dist/distrib. */
#ifndef _mutex_ext_h_
#define _mutex_ext_h_
void __db_mutex_init __P((db_mutex_t *, u_int32_t));
int __db_mutex_init __P((db_mutex_t *, u_int32_t));
int __db_mutex_lock __P((db_mutex_t *, int));
int __db_mutex_unlock __P((db_mutex_t *, int));
#endif /* _mutex_ext_h_ */

View File

@ -2,23 +2,29 @@
#ifndef _os_ext_h_
#define _os_ext_h_
int __db_abspath __P((const char *));
char *__db_strdup __P((const char *));
void *__db_calloc __P((size_t, size_t));
void *__db_malloc __P((size_t));
void *__db_realloc __P((void *, size_t));
int __os_oldwin __P((void));
int __os_dirlist __P((const char *, char ***, int *));
void __os_dirfree __P((char **, int));
int __db_fileid __P((DB_ENV *, const char *, int, u_int8_t *));
int __db_fsync __P((int));
int __os_map __P((int, size_t, int, int, void **));
int __os_unmap __P((void *, size_t));
int __db_oflags __P((int));
int __db_open __P((const char *, int, int, int, int *));
int __db_mapanon_ok __P((int));
int __db_mapinit __P((void));
int __db_mapregion __P((char *, REGINFO *));
int __db_unmapregion __P((REGINFO *));
int __db_unlinkregion __P((char *, REGINFO *));
int __db_mapfile __P((char *, int, size_t, int, void **));
int __db_unmapfile __P((void *, size_t));
u_int32_t __db_oflags __P((int));
int __db_omode __P((const char *));
int __db_open __P((const char *, u_int32_t, u_int32_t, int, int *));
int __db_close __P((int));
char *__db_rpath __P((const char *));
int __db_read __P((int, void *, size_t, ssize_t *));
int __db_write __P((int, void *, size_t, ssize_t *));
int __os_seek __P((int, size_t, db_pgno_t, u_long, int));
int __os_seek __P((int, size_t, db_pgno_t, u_int32_t, int, int));
int __os_sleep __P((u_long, u_long));
int __os_spin __P((void));
int __os_exists __P((const char *, int *));

View File

@ -1,40 +1,40 @@
/*-
* See the file LICENSE for redistribution information.
*
* Copyright (c) 1997
* Copyright (c) 1997, 1998
* Sleepycat Software. All rights reserved.
*
* @(#)os_func.h 10.5 (Sleepycat) 12/4/97
* @(#)os_func.h 10.8 (Sleepycat) 4/19/98
*/
/* Calls which can be replaced by the application. */
struct __db_jumptab {
int (*db_close) __P((int)); /* DB_FUNC_CLOSE */
void (*db_dirfree) __P((char **, int)); /* DB_FUNC_DIRFREE */
int (*db_dirlist) /* DB_FUNC_DIRLIST */
int (*j_close) __P((int)); /* DB_FUNC_CLOSE */
void (*j_dirfree) __P((char **, int)); /* DB_FUNC_DIRFREE */
int (*j_dirlist) /* DB_FUNC_DIRLIST */
__P((const char *, char ***, int *));
int (*db_exists) /* DB_FUNC_EXISTS */
int (*j_exists) /* DB_FUNC_EXISTS */
__P((const char *, int *));
void (*db_free) __P((void *)); /* DB_FUNC_FREE */
int (*db_fsync) __P((int)); /* DB_FUNC_FSYNC */
int (*db_ioinfo) __P((const char *, /* DB_FUNC_IOINFO */
void (*j_free) __P((void *)); /* DB_FUNC_FREE */
int (*j_fsync) __P((int)); /* DB_FUNC_FSYNC */
int (*j_ioinfo) __P((const char *, /* DB_FUNC_IOINFO */
int, u_int32_t *, u_int32_t *, u_int32_t *));
void *(*db_malloc) __P((size_t)); /* DB_FUNC_MALLOC */
int (*db_map) /* DB_FUNC_MAP */
__P((int, size_t, int, int, void **));
int (*db_open) /* DB_FUNC_OPEN */
void *(*j_malloc) __P((size_t)); /* DB_FUNC_MALLOC */
int (*j_map) /* DB_FUNC_MAP */
__P((char *, int, size_t, int, int, int, void **));
int (*j_open) /* DB_FUNC_OPEN */
__P((const char *, int, ...));
ssize_t (*db_read) __P((int, void *, size_t)); /* DB_FUNC_READ */
void *(*db_realloc) __P((void *, size_t)); /* DB_FUNC_REALLOC */
int (*db_seek) /* DB_FUNC_SEEK */
__P((int, size_t, db_pgno_t, u_long, int));
int (*db_sleep) __P((u_long, u_long)); /* DB_FUNC_SLEEP */
char *(*db_strdup) __P((const char *)); /* DB_FUNC_STRDUP */
int (*db_unlink) __P((const char *)); /* DB_FUNC_UNLINK */
int (*db_unmap) __P((void *, size_t)); /* DB_FUNC_UNMAP */
ssize_t (*db_write) /* DB_FUNC_WRITE */
ssize_t (*j_read) __P((int, void *, size_t)); /* DB_FUNC_READ */
void *(*j_realloc) __P((void *, size_t)); /* DB_FUNC_REALLOC */
int (*j_runlink) __P((char *)); /* DB_FUNC_RUNLINK */
int (*j_seek) /* DB_FUNC_SEEK */
__P((int, size_t, db_pgno_t, u_int32_t, int, int));
int (*j_sleep) __P((u_long, u_long)); /* DB_FUNC_SLEEP */
int (*j_unlink) __P((const char *)); /* DB_FUNC_UNLINK */
int (*j_unmap) __P((void *, size_t)); /* DB_FUNC_UNMAP */
ssize_t (*j_write) /* DB_FUNC_WRITE */
__P((int, const void *, size_t));
int (*db_yield) __P((void)); /* DB_FUNC_YIELD */
int (*j_yield) __P((void)); /* DB_FUNC_YIELD */
};
extern struct __db_jumptab __db_jump;
@ -43,7 +43,7 @@ extern struct __db_jumptab __db_jump;
* Names used by DB to call through the jump table.
*
* The naming scheme goes like this: if the functionality the application can
* replace is the same as the DB functionality, e.g., calloc, or dirlist, then
* replace is the same as the DB functionality, e.g., malloc, or dirlist, then
* we use the name __db_XXX, and the application is expected to replace the
* complete functionality, which may or may not map directly to an ANSI C or
* POSIX 1003.1 interface. If the functionality that the aplication replaces
@ -53,20 +53,17 @@ extern struct __db_jumptab __db_jump;
* part of DB is the only code that should use the __os_XXX names, all other
* parts of DB should be calling __db_XXX functions.
*/
#define __os_close __db_jump.db_close /* __db_close is a wrapper. */
#define __db_dirfree __db_jump.db_dirfree
#define __db_dirlist __db_jump.db_dirlist
#define __db_exists __db_jump.db_exists
#define __db_free __db_jump.db_free
#define __os_fsync __db_jump.db_fsync /* __db_fsync is a wrapper. */
#define __db_ioinfo __db_jump.db_ioinfo
#define __db_map __db_jump.db_map
#define __os_open __db_jump.db_open /* __db_open is a wrapper. */
#define __os_read __db_jump.db_read /* __db_read is a wrapper. */
#define __db_seek __db_jump.db_seek
#define __db_sleep __db_jump.db_sleep
#define __db_strdup __db_jump.db_strdup
#define __os_unlink __db_jump.db_unlink /* __db_unlink is a wrapper. */
#define __db_unmap __db_jump.db_unmap
#define __os_write __db_jump.db_write /* __db_write is a wrapper. */
#define __db_yield __db_jump.db_yield
#define __os_close __db_jump.j_close /* __db_close is a wrapper. */
#define __db_dirfree __db_jump.j_dirfree
#define __db_dirlist __db_jump.j_dirlist
#define __db_exists __db_jump.j_exists
#define __db_free __db_jump.j_free
#define __os_fsync __db_jump.j_fsync /* __db_fsync is a wrapper. */
#define __db_ioinfo __db_jump.j_ioinfo
#define __os_open __db_jump.j_open /* __db_open is a wrapper. */
#define __os_read __db_jump.j_read /* __db_read is a wrapper. */
#define __db_seek __db_jump.j_seek
#define __db_sleep __db_jump.j_sleep
#define __os_unlink __db_jump.j_unlink /* __db_unlink is a wrapper. */
#define __os_write __db_jump.j_write /* __db_write is a wrapper. */
#define __db_yield __db_jump.j_yield

View File

@ -1,10 +1,10 @@
/*-
* See the file LICENSE for redistribution information.
*
* Copyright (c) 1996, 1997
* Copyright (c) 1996, 1997, 1998
* Sleepycat Software. All rights reserved.
*
* @(#)shqueue.h 8.12 (Sleepycat) 9/10/97
* @(#)shqueue.h 8.13 (Sleepycat) 4/10/98
*/
#ifndef _SYS_SHQUEUE_H_
#define _SYS_SHQUEUE_H_

View File

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

View File

@ -1,28 +1,21 @@
/*-
* See the file LICENSE for redistribution information.
*
* Copyright (c) 1996, 1997
* Copyright (c) 1996, 1997, 1998
* Sleepycat Software. All rights reserved.
*/
#include "config.h"
#ifndef lint
static const char sccsid[] = "@(#)lock.c 10.43 (Sleepycat) 1/8/98";
static const char sccsid[] = "@(#)lock.c 10.52 (Sleepycat) 5/10/98";
#endif /* not lint */
#ifndef NO_SYSTEM_INCLUDES
#include <sys/types.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <errno.h>
#include <fcntl.h>
#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#endif
#include "db_int.h"
@ -34,248 +27,15 @@ static const char sccsid[] = "@(#)lock.c 10.43 (Sleepycat) 1/8/98";
#include "db_am.h"
static void __lock_checklocker __P((DB_LOCKTAB *, struct __db_lock *, int));
static int __lock_count_locks __P((DB_LOCKREGION *));
static int __lock_count_objs __P((DB_LOCKREGION *));
static int __lock_create __P((const char *, int, DB_ENV *));
static void __lock_freeobj __P((DB_LOCKTAB *, DB_LOCKOBJ *));
static int __lock_get_internal __P((DB_LOCKTAB *, u_int32_t, int, const DBT *,
db_lockmode_t, struct __db_lock **));
static int __lock_grow_region __P((DB_LOCKTAB *, int, size_t));
static int __lock_get_internal __P((DB_LOCKTAB *, u_int32_t, u_int32_t,
const DBT *, db_lockmode_t, struct __db_lock **));
static int __lock_put_internal __P((DB_LOCKTAB *, struct __db_lock *, int));
static void __lock_remove_waiter
__P((DB_LOCKTAB *, DB_LOCKOBJ *, struct __db_lock *, db_status_t));
static void __lock_reset_region __P((DB_LOCKTAB *));
static int __lock_validate_region __P((DB_LOCKTAB *));
#ifdef DEBUG
static void __lock_dump_locker __P((DB_LOCKTAB *, DB_LOCKOBJ *));
static void __lock_dump_object __P((DB_LOCKTAB *, DB_LOCKOBJ *));
static void __lock_printlock __P((DB_LOCKTAB *, struct __db_lock *, int));
#endif
/*
* Create and initialize a lock region in shared memory.
*/
/*
* __lock_create --
* Create the lock region. Returns an errno. In most cases,
* the errno should be that returned by __db_ropen, in which case
* an EAGAIN means that we should retry, and an EEXIST means that
* the region exists and we didn't need to create it. Any other
* sort of errno should be treated as a system error, leading to a
* failure of the original interface call.
*/
static int
__lock_create(path, mode, dbenv)
const char *path;
int mode;
DB_ENV *dbenv;
{
struct __db_lock *lp;
struct lock_header *tq_head;
struct obj_header *obj_head;
DB_LOCKOBJ *op;
DB_LOCKREGION *lrp;
u_int maxlocks;
u_int32_t i;
int fd, lock_modes, nelements, ret;
const u_int8_t *conflicts;
u_int8_t *curaddr;
maxlocks = dbenv == NULL || dbenv->lk_max == 0 ?
DB_LOCK_DEFAULT_N : dbenv->lk_max;
lock_modes = dbenv == NULL || dbenv->lk_modes == 0 ?
DB_LOCK_RW_N : dbenv->lk_modes;
conflicts = dbenv == NULL || dbenv->lk_conflicts == NULL ?
db_rw_conflicts : dbenv->lk_conflicts;
if ((ret =
__db_rcreate(dbenv, DB_APP_NONE, path, DB_DEFAULT_LOCK_FILE, mode,
LOCK_REGION_SIZE(lock_modes, maxlocks, __db_tablesize(maxlocks)),
0, &fd, &lrp)) != 0)
return (ret);
/* Region exists; now initialize it. */
lrp->table_size = __db_tablesize(maxlocks);
lrp->magic = DB_LOCKMAGIC;
lrp->version = DB_LOCKVERSION;
lrp->id = 0;
lrp->maxlocks = maxlocks;
lrp->need_dd = 0;
lrp->detect = DB_LOCK_NORUN;
lrp->numobjs = maxlocks;
lrp->nlockers = 0;
lrp->mem_bytes = ALIGN(STRING_SIZE(maxlocks), sizeof(size_t));
lrp->increment = lrp->hdr.size / 2;
lrp->nmodes = lock_modes;
lrp->nconflicts = 0;
lrp->nrequests = 0;
lrp->nreleases = 0;
lrp->ndeadlocks = 0;
/*
* As we write the region, we've got to maintain the alignment
* for the structures that follow each chunk. This information
* ends up being encapsulated both in here as well as in the
* lock.h file for the XXX_SIZE macros.
*/
/* Initialize conflict matrix. */
curaddr = (u_int8_t *)lrp + sizeof(DB_LOCKREGION);
memcpy(curaddr, conflicts, lock_modes * lock_modes);
curaddr += lock_modes * lock_modes;
/*
* Initialize hash table.
*/
curaddr = (u_int8_t *)ALIGNP(curaddr, LOCK_HASH_ALIGN);
lrp->hash_off = curaddr - (u_int8_t *)lrp;
nelements = lrp->table_size;
__db_hashinit(curaddr, nelements);
curaddr += nelements * sizeof(DB_HASHTAB);
/*
* Initialize locks onto a free list. Since locks contains mutexes,
* we need to make sure that each lock is aligned on a MUTEX_ALIGNMENT
* boundary.
*/
curaddr = (u_int8_t *)ALIGNP(curaddr, MUTEX_ALIGNMENT);
tq_head = &lrp->free_locks;
SH_TAILQ_INIT(tq_head);
for (i = 0; i++ < maxlocks;
curaddr += ALIGN(sizeof(struct __db_lock), MUTEX_ALIGNMENT)) {
lp = (struct __db_lock *)curaddr;
lp->status = DB_LSTAT_FREE;
SH_TAILQ_INSERT_HEAD(tq_head, lp, links, __db_lock);
}
/* Initialize objects onto a free list. */
obj_head = &lrp->free_objs;
SH_TAILQ_INIT(obj_head);
for (i = 0; i++ < maxlocks; curaddr += sizeof(DB_LOCKOBJ)) {
op = (DB_LOCKOBJ *)curaddr;
SH_TAILQ_INSERT_HEAD(obj_head, op, links, __db_lockobj);
}
/*
* Initialize the string space; as for all shared memory allocation
* regions, this requires size_t alignment, since we store the
* lengths of malloc'd areas in the area..
*/
curaddr = (u_int8_t *)ALIGNP(curaddr, sizeof(size_t));
lrp->mem_off = curaddr - (u_int8_t *)lrp;
__db_shalloc_init(curaddr, lrp->mem_bytes);
/* Release the lock. */
(void)__db_mutex_unlock(&lrp->hdr.lock, fd);
/* Now unmap the region. */
if ((ret = __db_rclose(dbenv, fd, lrp)) != 0) {
(void)lock_unlink(path, 1 /* force */, dbenv);
return (ret);
}
return (0);
}
int
lock_open(path, flags, mode, dbenv, ltp)
const char *path;
int flags, mode;
DB_ENV *dbenv;
DB_LOCKTAB **ltp;
{
DB_LOCKTAB *lt;
int ret, retry_cnt;
/* Validate arguments. */
#ifdef HAVE_SPINLOCKS
#define OKFLAGS (DB_CREATE | DB_THREAD)
#else
#define OKFLAGS (DB_CREATE)
#endif
if ((ret = __db_fchk(dbenv, "lock_open", flags, OKFLAGS)) != 0)
return (ret);
/*
* Create the lock table structure.
*/
if ((lt = (DB_LOCKTAB *)__db_calloc(1, sizeof(DB_LOCKTAB))) == NULL) {
__db_err(dbenv, "%s", strerror(ENOMEM));
return (ENOMEM);
}
lt->dbenv = dbenv;
/*
* Now, create the lock region if it doesn't already exist.
*/
retry_cnt = 0;
retry: if (LF_ISSET(DB_CREATE) &&
(ret = __lock_create(path, mode, dbenv)) != 0)
if (ret == EAGAIN && ++retry_cnt < 3) {
(void)__db_sleep(1, 0);
goto retry;
} else if (ret == EEXIST) /* We did not create the region */
LF_CLR(DB_CREATE);
else
goto out;
/*
* Finally, open the region, map it in, and increment the
* reference count.
*/
retry_cnt = 0;
retry1: if ((ret = __db_ropen(dbenv, DB_APP_NONE, path, DB_DEFAULT_LOCK_FILE,
LF_ISSET(~(DB_CREATE | DB_THREAD)), &lt->fd, &lt->region)) != 0) {
if (ret == EAGAIN && ++retry_cnt < 3) {
(void)__db_sleep(1, 0);
goto retry1;
}
goto out;
}
if (lt->region->magic != DB_LOCKMAGIC) {
__db_err(dbenv, "lock_open: Bad magic number");
ret = EINVAL;
goto out;
}
/* Check for automatic deadlock detection. */
if (dbenv->lk_detect != DB_LOCK_NORUN) {
if (lt->region->detect != DB_LOCK_NORUN &&
dbenv->lk_detect != DB_LOCK_DEFAULT &&
lt->region->detect != dbenv->lk_detect) {
__db_err(dbenv,
"lock_open: incompatible deadlock detector mode");
ret = EINVAL;
goto out;
}
if (lt->region->detect == DB_LOCK_NORUN)
lt->region->detect = dbenv->lk_detect;
}
/* Set up remaining pointers into region. */
lt->conflicts = (u_int8_t *)lt->region + sizeof(DB_LOCKREGION);
lt->hashtab =
(DB_HASHTAB *)((u_int8_t *)lt->region + lt->region->hash_off);
lt->mem = (void *)((u_int8_t *)lt->region + lt->region->mem_off);
lt->reg_size = lt->region->hdr.size;
*ltp = lt;
return (0);
/* Error handling. */
out: if (lt->region != NULL)
(void)__db_rclose(lt->dbenv, lt->fd, lt->region);
if (LF_ISSET(DB_CREATE))
(void)lock_unlink(path, 1, lt->dbenv);
__db_free(lt);
return (ret);
}
int
lock_id (lt, idp)
lock_id(lt, idp)
DB_LOCKTAB *lt;
u_int32_t *idp;
{
@ -294,8 +54,8 @@ lock_id (lt, idp)
int
lock_vec(lt, locker, flags, list, nlist, elistp)
DB_LOCKTAB *lt;
u_int32_t locker;
int flags, nlist;
u_int32_t locker, flags;
int nlist;
DB_LOCKREQ *list, **elistp;
{
struct __db_lock *lp;
@ -345,7 +105,7 @@ lock_vec(lt, locker, flags, list, nlist, elistp)
for (lp = SH_LIST_FIRST(&sh_locker->heldby, __db_lock);
lp != NULL;
lp = SH_LIST_FIRST(&sh_locker->heldby, __db_lock)) {
if ((ret = __lock_put_internal(lt, lp, 0)) != 0)
if ((ret = __lock_put_internal(lt, lp, 1)) != 0)
break;
}
__lock_freeobj(lt, sh_locker);
@ -436,8 +196,7 @@ lock_vec(lt, locker, flags, list, nlist, elistp)
int
lock_get(lt, locker, flags, obj, lock_mode, lock)
DB_LOCKTAB *lt;
u_int32_t locker;
int flags;
u_int32_t locker, flags;
const DBT *obj;
db_lockmode_t lock_mode;
DB_LOCK *lock;
@ -496,35 +255,6 @@ lock_put(lt, lock)
return (ret);
}
int
lock_close(lt)
DB_LOCKTAB *lt;
{
int ret;
if ((ret = __db_rclose(lt->dbenv, lt->fd, lt->region)) != 0)
return (ret);
/* Free lock table. */
__db_free(lt);
return (0);
}
int
lock_unlink(path, force, dbenv)
const char *path;
int force;
DB_ENV *dbenv;
{
return (__db_runlink(dbenv,
DB_APP_NONE, path, DB_DEFAULT_LOCK_FILE, force));
}
/*
* XXX This looks like it could be void, but I'm leaving it returning
* an int because I think it will have to when we go through and add
* the appropriate error checking for the EINTR on mutexes.
*/
static int
__lock_put_internal(lt, lockp, do_all)
DB_LOCKTAB *lt;
@ -593,7 +323,7 @@ __lock_put_internal(lt, lockp, do_all)
SH_TAILQ_INSERT_TAIL(&sh_obj->holders, lp_w, links);
/* Wake up waiter. */
(void)__db_mutex_unlock(&lp_w->mutex, lt->fd);
(void)__db_mutex_unlock(&lp_w->mutex, lt->reginfo.fd);
state_changed = 1;
}
@ -626,8 +356,7 @@ __lock_put_internal(lt, lockp, do_all)
static int
__lock_get_internal(lt, locker, flags, obj, lock_mode, lockp)
DB_LOCKTAB *lt;
u_int32_t locker;
int flags;
u_int32_t locker, flags;
const DBT *obj;
db_lockmode_t lock_mode;
struct __db_lock **lockp;
@ -741,7 +470,7 @@ __lock_get_internal(lt, locker, flags, obj, lock_mode, lockp)
*/
(void)__db_mutex_init(&newl->mutex,
MUTEX_LOCK_OFFSET(lt->region, &newl->mutex));
(void)__db_mutex_lock(&newl->mutex, lt->fd);
(void)__db_mutex_lock(&newl->mutex, lt->reginfo.fd);
/*
* Now, insert the lock onto its locker's list.
@ -772,7 +501,7 @@ __lock_get_internal(lt, locker, flags, obj, lock_mode, lockp)
if (lrp->detect != DB_LOCK_NORUN)
ret = lock_detect(lt, 0, lrp->detect);
(void)__db_mutex_lock(&newl->mutex, lt->fd);
(void)__db_mutex_lock(&newl->mutex, lt->reginfo.fd);
LOCK_LOCKREGION(lt);
if (newl->status != DB_LSTAT_PENDING) {
@ -801,306 +530,6 @@ __lock_get_internal(lt, locker, flags, obj, lock_mode, lockp)
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 --
*
@ -1136,7 +565,12 @@ __lock_is_locked(lt, locker, dbt, mode)
return (0);
}
static void
/*
* __lock_printlock --
*
* PUBLIC: void __lock_printlock __P((DB_LOCKTAB *, struct __db_lock *, int));
*/
void
__lock_printlock(lt, lp, ispgno)
DB_LOCKTAB *lt;
struct __db_lock *lp;
@ -1213,39 +647,6 @@ __lock_printlock(lt, lp, ispgno)
printf("\n");
}
}
#endif
static int
__lock_count_locks(lrp)
DB_LOCKREGION *lrp;
{
struct __db_lock *newl;
int count;
count = 0;
for (newl = SH_TAILQ_FIRST(&lrp->free_locks, __db_lock);
newl != NULL;
newl = SH_TAILQ_NEXT(newl, links, __db_lock))
count++;
return (count);
}
static int
__lock_count_objs(lrp)
DB_LOCKREGION *lrp;
{
DB_LOCKOBJ *obj;
int count;
count = 0;
for (obj = SH_TAILQ_FIRST(&lrp->free_objs, __db_lockobj);
obj != NULL;
obj = SH_TAILQ_NEXT(obj, links, __db_lockobj))
count++;
return (count);
}
/*
* PUBLIC: int __lock_getobj __P((DB_LOCKTAB *,
@ -1354,19 +755,7 @@ __lock_remove_waiter(lt, sh_obj, lockp, status)
lockp->status = status;
/* Wake whoever is waiting on this lock. */
(void)__db_mutex_unlock(&lockp->mutex, lt->fd);
}
static void
__lock_freeobj(lt, obj)
DB_LOCKTAB *lt;
DB_LOCKOBJ *obj;
{
HASHREMOVE_EL(lt->hashtab,
__db_lockobj, links, obj, lt->region->table_size, __lock_lhash);
if (obj->lockobj.size > sizeof(obj->objdata))
__db_shalloc_free(lt->mem, SH_DBT_PTR(&obj->lockobj));
SH_TAILQ_INSERT_HEAD(&lt->region->free_objs, obj, links, __db_lockobj);
(void)__db_mutex_unlock(&lockp->mutex, lt->reginfo.fd);
}
static void
@ -1389,12 +778,13 @@ __lock_checklocker(lt, lockp, do_remove)
}
static void
__lock_reset_region(lt)
__lock_freeobj(lt, obj)
DB_LOCKTAB *lt;
DB_LOCKOBJ *obj;
{
lt->conflicts = (u_int8_t *)lt->region + sizeof(DB_LOCKREGION);
lt->hashtab =
(DB_HASHTAB *)((u_int8_t *)lt->region + lt->region->hash_off);
lt->mem = (void *)((u_int8_t *)lt->region + lt->region->mem_off);
lt->reg_size = lt->region->hdr.size;
HASHREMOVE_EL(lt->hashtab,
__db_lockobj, links, obj, lt->region->table_size, __lock_lhash);
if (obj->lockobj.size > sizeof(obj->objdata))
__db_shalloc_free(lt->mem, SH_DBT_PTR(&obj->lockobj));
SH_TAILQ_INSERT_HEAD(&lt->region->free_objs, obj, links, __db_lockobj);
}

View File

@ -1,14 +1,14 @@
/*-
* See the file LICENSE for redistribution information.
*
* Copyright (c) 1996, 1997
* Copyright (c) 1996, 1997, 1998
* Sleepycat Software. All rights reserved.
*/
#include "config.h"
#ifndef lint
static const char sccsid[] = "@(#)lock_conflict.c 10.2 (Sleepycat) 6/21/97";
static const char sccsid[] = "@(#)lock_conflict.c 10.3 (Sleepycat) 4/10/98";
#endif /* not lint */
#ifndef NO_SYSTEM_INCLUDES

View File

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

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.
*
* Copyright (c) 1996, 1997
* Copyright (c) 1996, 1997, 1998
* Sleepycat Software. All rights reserved.
*/
#include "config.h"
#ifndef lint
static const char sccsid[] = "@(#)lock_util.c 10.5 (Sleepycat) 1/8/98";
static const char sccsid[] = "@(#)lock_util.c 10.9 (Sleepycat) 4/26/98";
#endif /* not lint */
#ifndef NO_SYSTEM_INCLUDES
#include <sys/types.h>
#include <fcntl.h>
#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#endif
#include "db_int.h"
@ -30,11 +25,13 @@ static const char sccsid[] = "@(#)lock_util.c 10.5 (Sleepycat) 1/8/98";
#include "lock.h"
/*
* __lock_cmp --
* This function is used to compare a DBT that is about to be entered
* into a hash table with an object already in the hash table. Note
* that it just returns true on equal and 0 on not-equal. Therefore this
* cannot be used as a sort function; its purpose is to be used as a
* hash comparison function.
* that it just returns true on equal and 0 on not-equal. Therefore
* this function cannot be used as a sort function; its purpose is to
* be used as a hash comparison function.
*
* PUBLIC: int __lock_cmp __P((const DBT *, DB_LOCKOBJ *));
*/
int
@ -46,6 +43,7 @@ __lock_cmp(dbt, lock_obj)
if (lock_obj->type != DB_LOCK_OBJTYPE)
return (0);
obj_data = SH_DBT_PTR(&lock_obj->lockobj);
return (dbt->size == lock_obj->lockobj.size &&
memcmp(dbt->data, obj_data, dbt->size) == 0);
@ -69,35 +67,86 @@ __lock_locker_cmp(locker, lock_obj)
}
/*
* PUBLIC: int __lock_ohash __P((const DBT *));
* The next two functions are the hash functions used to store objects in the
* lock hash table. They are hashing the same items, but one (__lock_ohash)
* takes a DBT (used for hashing a parameter passed from the user) and the
* other (__lock_lhash) takes a DB_LOCKOBJ (used for hashing something that is
* already in the lock manager). In both cases, we have a special check to
* fast path the case where we think we are doing a hash on a DB page/fileid
* pair. If the size is right, then we do the fast hash.
*
* We know that DB uses struct __db_ilocks for its lock objects. The first
* four bytes are the 4-byte page number and the next DB_FILE_ID_LEN bytes
* are a unique file id, where the first 4 bytes on UNIX systems are the file
* inode number, and the first 4 bytes on Windows systems are the FileIndexLow
* bytes. So, we use the XOR of the page number and the first four bytes of
* the file id to produce a 32-bit hash value.
*
* We have no particular reason to believe that this algorithm will produce
* a good hash, but we want a fast hash more than we want a good one, when
* we're coming through this code path.
*/
int
#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)
const DBT *dbt;
{
if (dbt->size == sizeof(struct __db_ilock))
FAST_HASH(dbt->data);
return (__ham_func5(dbt->data, dbt->size));
}
/*
* PUBLIC: u_int32_t __lock_locker_hash __P((u_int32_t));
*/
u_int32_t
__lock_locker_hash(locker)
u_int32_t locker;
{
return (__ham_func5(&locker, sizeof(locker)));
}
/*
* __lock_lhash --
*
* PUBLIC: u_int32_t __lock_lhash __P((DB_LOCKOBJ *));
*/
u_int32_t
__lock_lhash(lock_obj)
DB_LOCKOBJ *lock_obj;
{
u_int32_t tmp;
void *obj_data;
obj_data = SH_DBT_PTR(&lock_obj->lockobj);
if (lock_obj->type == DB_LOCK_LOCKER) {
memcpy(&tmp, obj_data, sizeof(u_int32_t));
return (tmp);
}
if (lock_obj->lockobj.size == sizeof(struct __db_ilock))
FAST_HASH(obj_data);
return (__ham_func5(obj_data, lock_obj->lockobj.size));
}
/*
* __lock_locker_hash --
* Hash function for entering lockers into the hash table. Since these
* are simply 32-bit unsigned integers, just return the locker value.
*
* PUBLIC: u_int32_t __lock_locker_hash __P((u_int32_t));
*/
u_int32_t
__lock_locker_hash(locker)
u_int32_t locker;
{
return (locker);
}

View File

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

View File

@ -1,43 +1,12 @@
/*-
* See the file LICENSE for redistribution information.
*
* Copyright (c) 1996, 1997
* Copyright (c) 1996, 1997, 1998
* Sleepycat Software. All rights reserved.
*
* @(#)log.src 10.4 (Sleepycat) 1/17/98
*
* This is the source file used to create the logging functions for the
* log package. Each access method (or set of routines wishing to register
* record types with the transaction system) should have a file like this.
* Each type of log record and its parameters is defined. The basic
* format of a record definition is:
*
* BEGIN <RECORD_TYPE>
* ARG|STRING|POINTER <variable name> <variable type> <printf format>
* ...
* END
* ARG the argument is a simple parameter of the type * specified.
* DBT the argument is a DBT (db.h) containing a length and pointer.
* PTR the argument is a pointer to the data type specified; the entire
* type should be logged.
*
* There are a set of shell scripts of the form xxx.sh that generate c
* code and or h files to process these. (This is probably better done
* in a single PERL script, but for now, this works.)
*
* The DB recovery system requires the following three fields appear in
* every record, and will assign them to the per-record-type structures
* as well as making them the first parameters to the appropriate logging
* call.
* rectype: record-type, identifies the structure and log/read call
* txnid: transaction id, a DBT in this implementation
* prev: the last LSN for this transaction
* @(#)log.src 10.5 (Sleepycat) 4/10/98
*/
/*
* Use the argument of PREFIX as the prefix for all record types,
* routines, id numbers, etc.
*/
PREFIX log
/* Used for registering name/id translations at open or close. */

View File

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

View File

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

View File

@ -1,13 +1,13 @@
/*-
* See the file LICENSE for redistribution information.
*
* Copyright (c) 1996, 1997
* Copyright (c) 1996, 1997, 1998
* Sleepycat Software. All rights reserved.
*/
#include "config.h"
#ifndef lint
static const char sccsid[] = "@(#)log_compare.c 10.2 (Sleepycat) 6/21/97";
static const char sccsid[] = "@(#)log_compare.c 10.3 (Sleepycat) 4/10/98";
#endif /* not lint */
#ifndef NO_SYSTEM_INCLUDES

View File

@ -1,21 +1,20 @@
/*-
* See the file LICENSE for redistribution information.
*
* Copyright (c) 1996, 1997
* Copyright (c) 1996, 1997, 1998
* Sleepycat Software. All rights reserved.
*/
#include "config.h"
#ifndef lint
static const char sccsid[] = "@(#)log_findckp.c 10.12 (Sleepycat) 10/25/97";
static const char sccsid[] = "@(#)log_findckp.c 10.15 (Sleepycat) 4/26/98";
#endif /* not lint */
#ifndef NO_SYSTEM_INCLUDES
#include <sys/types.h>
#include <errno.h>
#include <stdlib.h>
#include <string.h>
#endif
@ -44,10 +43,10 @@ static const char sccsid[] = "@(#)log_findckp.c 10.12 (Sleepycat) 10/25/97";
* We find one at 500. This means that we can truncate the log before
* 500 or run recovery beginning at 500.
*
* Returns 0 if we find a checkpoint.
* Returns 0 if we find a suitable checkpoint or we retrieved the
* first record in the log from which to start.
* Returns DB_NOTFOUND if there are no log records.
* Returns errno on error.
* Returns DB_NOTFOUND if we could not find a suitable start point and
* we should start from the beginning.
*
* PUBLIC: int __log_findckp __P((DB_LOG *, DB_LSN *));
*/
@ -70,9 +69,12 @@ __log_findckp(lp, lsnp)
memset(&data, 0, sizeof(data));
if (F_ISSET(lp, DB_AM_THREAD))
F_SET(&data, DB_DBT_MALLOC);
if ((ret = log_get(lp, &last_ckp, &data, DB_CHECKPOINT)) != 0)
return (ret == ENOENT ? DB_NOTFOUND : ret);
ZERO_LSN(ckp_lsn);
if ((ret = log_get(lp, &last_ckp, &data, DB_CHECKPOINT)) != 0)
if (ret == ENOENT)
goto get_first;
else
return (ret);
next_lsn = last_ckp;
do {
@ -115,16 +117,12 @@ __log_findckp(lp, lsnp)
* beginning of the log.
*/
if (log_compare(&last_ckp, &ckp_lsn) > 0) {
if ((ret = log_get(lp, &last_ckp, &data, DB_FIRST)) != 0)
get_first: if ((ret = log_get(lp, &last_ckp, &data, DB_FIRST)) != 0)
return (ret);
if (F_ISSET(lp, DB_AM_THREAD))
__db_free(data.data);
}
*lsnp = last_ckp;
if (verbose)
__db_err(lp->dbenv, "Rolling forward from [%lu][%lu]",
(u_long)last_ckp.file, (u_long)last_ckp.offset);
return (IS_ZERO_LSN(last_ckp) ? DB_NOTFOUND : 0);
}

View File

@ -1,21 +1,19 @@
/*-
* See the file LICENSE for redistribution information.
*
* Copyright (c) 1996, 1997
* Copyright (c) 1996, 1997, 1998
* Sleepycat Software. All rights reserved.
*/
#include "config.h"
#ifndef lint
static const char sccsid[] = "@(#)log_get.c 10.24 (Sleepycat) 1/17/98";
static const char sccsid[] = "@(#)log_get.c 10.32 (Sleepycat) 5/6/98";
#endif /* not lint */
#ifndef NO_SYSTEM_INCLUDES
#include <sys/types.h>
#include <errno.h>
#include <fcntl.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#endif
@ -36,9 +34,8 @@ log_get(dblp, alsn, dbt, flags)
DB_LOG *dblp;
DB_LSN *alsn;
DBT *dbt;
int flags;
u_int32_t flags;
{
LOG *lp;
int ret;
/* Validate arguments. */
@ -66,8 +63,6 @@ log_get(dblp, alsn, dbt, flags)
return (__db_ferr(dblp->dbenv, "threaded data", 1));
}
lp = dblp->lp;
LOCK_LOGREGION(dblp);
/*
@ -97,14 +92,15 @@ log_get(dblp, alsn, dbt, flags)
* __log_get --
* Get a log record; internal version.
*
* PUBLIC: int __log_get __P((DB_LOG *, DB_LSN *, DBT *, int, int));
* PUBLIC: int __log_get __P((DB_LOG *, DB_LSN *, DBT *, u_int32_t, int));
*/
int
__log_get(dblp, alsn, dbt, flags, silent)
DB_LOG *dblp;
DB_LSN *alsn;
DBT *dbt;
int flags, silent;
u_int32_t flags;
int silent;
{
DB_LSN nlsn;
HDR hdr;
@ -122,7 +118,7 @@ __log_get(dblp, alsn, dbt, flags, silent)
nlsn = dblp->c_lsn;
switch (flags) {
case DB_CHECKPOINT:
nlsn = lp->c_lsn;
nlsn = lp->chkpt_lsn;
if (IS_ZERO_LSN(nlsn)) {
__db_err(dblp->dbenv,
"log_get: unable to find checkpoint record: no checkpoint set.");
@ -219,7 +215,8 @@ retry:
}
/* Seek to the header offset and read the header. */
if ((ret = __db_seek(dblp->c_fd, 0, 0, nlsn.offset, SEEK_SET)) != 0) {
if ((ret =
__db_seek(dblp->c_fd, 0, 0, nlsn.offset, 0, SEEK_SET)) != 0) {
fail = "seek";
goto err1;
}
@ -272,7 +269,13 @@ retry:
goto cksum;
}
/* Allocate temporary memory to hold the record. */
/*
* Allocate temporary memory to hold the record.
*
* XXX
* We're calling malloc(3) with a region locked. This isn't
* a good idea.
*/
if ((tbuf = (char *)__db_malloc(len)) == NULL) {
ret = ENOMEM;
goto err1;

View File

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

View File

@ -1,7 +1,7 @@
/*-
* See the file LICENSE for redistribution information.
*
* Copyright (c) 1996, 1997
* Copyright (c) 1996, 1997, 1998
* Sleepycat Software. All rights reserved.
*/
/*
@ -40,16 +40,13 @@
#include "config.h"
#ifndef lint
static const char sccsid[] = "@(#)log_rec.c 10.16 (Sleepycat) 1/17/98";
static const char sccsid[] = "@(#)log_rec.c 10.20 (Sleepycat) 4/28/98";
#endif /* not lint */
#ifndef NO_SYSTEM_INCLUDES
#include <sys/types.h>
#include <errno.h>
#include <fcntl.h>
#include <stddef.h>
#include <stdlib.h>
#include <string.h>
#endif
@ -121,6 +118,7 @@ __log_register_recover(logp, dbtp, lsnp, redo, info)
if (!logp->dbentry[argp->id].deleted)
ret = EINVAL;
} else if (--logp->dbentry[argp->id].refcount == 0) {
F_SET(logp->dbentry[argp->id].dbp, DB_AM_RECOVER);
ret = logp->dbentry[argp->id].dbp->close(
logp->dbentry[argp->id].dbp, 0);
logp->dbentry[argp->id].dbp = NULL;

View File

@ -1,20 +1,19 @@
/*-
* See the file LICENSE for redistribution information.
*
* Copyright (c) 1996, 1997
* Copyright (c) 1996, 1997, 1998
* Sleepycat Software. All rights reserved.
*/
#include "config.h"
#ifndef lint
static const char sccsid[] = "@(#)log_register.c 10.14 (Sleepycat) 1/19/98";
static const char sccsid[] = "@(#)log_register.c 10.18 (Sleepycat) 5/3/98";
#endif /* not lint */
#ifndef NO_SYSTEM_INCLUDES
#include <sys/types.h>
#include <errno.h>
#include <stdlib.h>
#include <string.h>
#endif
@ -42,12 +41,12 @@ log_register(dblp, dbp, name, type, idp)
u_int32_t fid;
int inserted, ret;
char *fullname;
void *fidp, *namep;
void *namep;
fid = 0;
inserted = 0;
fullname = NULL;
fnp = fidp = namep = NULL;
fnp = namep = NULL;
/* Check the arguments. */
if (type != DB_BTREE && type != DB_HASH && type != DB_RECNO) {
@ -57,7 +56,7 @@ log_register(dblp, dbp, name, type, idp)
/* Get the log file id. */
if ((ret = __db_appname(dblp->dbenv,
DB_APP_DATA, NULL, name, NULL, &fullname)) != 0)
DB_APP_DATA, NULL, name, 0, NULL, &fullname)) != 0)
return (ret);
LOCK_LOGREGION(dblp);
@ -70,8 +69,7 @@ log_register(dblp, dbp, name, type, idp)
fnp != NULL; fnp = SH_TAILQ_NEXT(fnp, q, __fname)) {
if (fid <= fnp->id)
fid = fnp->id + 1;
if (!memcmp(dbp->lock.fileid,
R_ADDR(dblp, fnp->fileid_off), DB_FILE_ID_LEN)) {
if (!memcmp(dbp->lock.fileid, fnp->ufid, DB_FILE_ID_LEN)) {
++fnp->ref;
fid = fnp->id;
goto found;
@ -84,15 +82,7 @@ log_register(dblp, dbp, name, type, idp)
fnp->ref = 1;
fnp->id = fid;
fnp->s_type = type;
if ((ret = __db_shalloc(dblp->addr, DB_FILE_ID_LEN, 0, &fidp)) != 0)
goto err;
/*
* XXX Now that uids are fixed size, we can put them in the fnp
* structure.
*/
fnp->fileid_off = R_OFFSET(dblp, fidp);
memcpy(fidp, dbp->lock.fileid, DB_FILE_ID_LEN);
memcpy(fnp->ufid, dbp->lock.fileid, DB_FILE_ID_LEN);
len = strlen(name) + 1;
if ((ret = __db_shalloc(dblp->addr, len, 0, &namep)) != 0)
@ -126,8 +116,6 @@ err: /*
SH_TAILQ_REMOVE(&dblp->lp->fq, fnp, q, __fname);
if (namep != NULL)
__db_shalloc_free(dblp->addr, namep);
if (fidp != NULL)
__db_shalloc_free(dblp->addr, fidp);
if (fnp != NULL)
__db_shalloc_free(dblp->addr, fnp);
}
@ -176,7 +164,7 @@ log_unregister(dblp, fid)
r_name.data = R_ADDR(dblp, fnp->name_off);
r_name.size = strlen(r_name.data) + 1;
memset(&fid_dbt, 0, sizeof(fid_dbt));
fid_dbt.data = R_ADDR(dblp, fnp->fileid_off);
fid_dbt.data = fnp->ufid;
fid_dbt.size = DB_FILE_ID_LEN;
if ((ret = __log_register_log(dblp, NULL, &r_unused,
0, LOG_CLOSE, &r_name, &fid_dbt, fid, fnp->s_type)) != 0)
@ -190,7 +178,6 @@ log_unregister(dblp, fid)
if (fnp->ref > 1)
--fnp->ref;
else {
__db_shalloc_free(dblp->addr, R_ADDR(dblp, fnp->fileid_off));
__db_shalloc_free(dblp->addr, R_ADDR(dblp, fnp->name_off));
SH_TAILQ_REMOVE(&dblp->lp->fq, fnp, q, __fname);
__db_shalloc_free(dblp->addr, fnp);

View File

@ -1,13 +1,13 @@
/*-
* See the file LICENSE for redistribution information.
*
* Copyright (c) 1996, 1997
* Copyright (c) 1996, 1997, 1998
* Sleepycat Software. All rights reserved.
*/
#include "config.h"
#ifndef lint
static const char sccsid[] = "@(#)mp_bh.c 10.28 (Sleepycat) 1/8/98";
static const char sccsid[] = "@(#)mp_bh.c 10.38 (Sleepycat) 5/20/98";
#endif /* not lint */
#ifndef NO_SYSTEM_INCLUDES
@ -59,8 +59,10 @@ __memp_bhwrite(dbmp, mfp, bhp, restartp, wrotep)
dbmfp != NULL; dbmfp = TAILQ_NEXT(dbmfp, q))
if (dbmfp->mfp == mfp) {
if (F_ISSET(dbmfp, MP_READONLY) &&
__memp_upgrade(dbmp, dbmfp, mfp))
__memp_upgrade(dbmp, dbmfp, mfp)) {
UNLOCKHANDLE(dbmp, dbmp->mutexp);
return (0);
}
break;
}
UNLOCKHANDLE(dbmp, dbmp->mutexp);
@ -111,8 +113,8 @@ __memp_bhwrite(dbmp, mfp, bhp, restartp, wrotep)
if (F_ISSET(mfp, MP_TEMP))
return (0);
if (__memp_fopen(dbmp, mfp, R_ADDR(dbmp, mfp->path_off), mfp->ftype,
0, 0, mfp->stat.st_pagesize, 0, NULL, NULL, 0, &dbmfp) != 0)
if (__memp_fopen(dbmp, mfp, R_ADDR(dbmp, mfp->path_off),
0, 0, mfp->stat.st_pagesize, 0, NULL, &dbmfp) != 0)
return (0);
found: return (__memp_pgwrite(dbmfp, bhp, restartp, wrotep));
@ -152,7 +154,7 @@ __memp_pgread(dbmfp, bhp, can_create)
ret = 0;
LOCKHANDLE(dbmp, dbmfp->mutexp);
if (dbmfp->fd == -1 || (ret =
__db_seek(dbmfp->fd, pagesize, bhp->pgno, 0, SEEK_SET)) != 0) {
__db_seek(dbmfp->fd, pagesize, bhp->pgno, 0, 0, SEEK_SET)) != 0) {
if (!can_create) {
if (dbmfp->fd == -1)
ret = EINVAL;
@ -164,8 +166,17 @@ __memp_pgread(dbmfp, bhp, can_create)
}
UNLOCKHANDLE(dbmp, dbmfp->mutexp);
/* Clear any uninitialized data. */
/* Clear the created page. */
if (mfp->clear_len == 0)
memset(bhp->buf, 0, pagesize);
else {
memset(bhp->buf, 0, mfp->clear_len);
#ifdef DIAGNOSTIC
memset(bhp->buf + mfp->clear_len,
0xff, pagesize - mfp->clear_len);
#endif
}
goto pgin;
}
@ -186,7 +197,15 @@ __memp_pgread(dbmfp, bhp, can_create)
goto err;
}
/* Clear any uninitialized data. */
/*
* If we didn't fail until we tried the read, don't clear the
* whole page, it wouldn't be insane for a filesystem to just
* always behave that way. Else, clear any uninitialized data.
*/
if (nr == 0)
memset(bhp->buf, 0,
mfp->clear_len == 0 ? pagesize : mfp->clear_len);
else
memset(bhp->buf + nr, 0, pagesize - nr);
}
@ -308,31 +327,31 @@ __memp_pgwrite(dbmfp, bhp, restartp, wrotep)
/* Temporary files may not yet have been created. */
LOCKHANDLE(dbmp, dbmfp->mutexp);
if (dbmfp->fd == -1)
if ((ret = __db_appname(dbenv, DB_APP_TMP,
NULL, NULL, &dbmfp->fd, NULL)) != 0 || dbmfp->fd == -1) {
if (dbmfp->fd == -1 &&
((ret = __db_appname(dbenv, DB_APP_TMP, NULL, NULL,
DB_CREATE | DB_EXCL | DB_TEMPORARY, &dbmfp->fd, NULL)) != 0 ||
dbmfp->fd == -1)) {
UNLOCKHANDLE(dbmp, dbmfp->mutexp);
__db_err(dbenv,
"unable to create temporary backing file");
__db_err(dbenv, "unable to create temporary backing file");
goto err;
}
/* Write the page out. */
if ((ret = __db_seek(dbmfp->fd, pagesize, bhp->pgno, 0, SEEK_SET)) != 0)
/*
* Write the page out.
*
* XXX
* Shut the compiler up; it doesn't understand the correlation between
* the failing clauses to __db_lseek and __db_write and this ret != 0.
*/
COMPQUIET(fail, NULL);
if ((ret =
__db_seek(dbmfp->fd, pagesize, bhp->pgno, 0, 0, SEEK_SET)) != 0)
fail = "seek";
else if ((ret = __db_write(dbmfp->fd, bhp->buf, pagesize, &nw)) != 0)
fail = "write";
UNLOCKHANDLE(dbmp, dbmfp->mutexp);
if (ret != 0) {
/*
* XXX
* Shut the compiler up; it doesn't understand the correlation
* between the failing clauses to __db_lseek and __db_write and
* this ret != 0.
*/
COMPQUIET(fail, NULL);
if (ret != 0)
goto syserr;
}
if (nw != (ssize_t)pagesize) {
ret = EIO;
@ -548,7 +567,7 @@ __memp_upgrade(dbmp, dbmfp, mfp)
* way we could have gotten a file descriptor of any kind.
*/
if ((ret = __db_appname(dbmp->dbenv, DB_APP_DATA,
NULL, R_ADDR(dbmp, mfp->path_off), NULL, &rpath)) != 0)
NULL, R_ADDR(dbmp, mfp->path_off), 0, NULL, &rpath)) != 0)
return (ret);
if (__db_open(rpath, 0, 0, 0, &fd) != 0) {
F_SET(dbmfp, MP_UPGRADE_FAIL);

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