summary refs log tree commit diff
path: root/db2
diff options
context:
space:
mode:
Diffstat (limited to 'db2')
-rw-r--r--db2/Makefile2
-rw-r--r--db2/btree/bt_close.c4
-rw-r--r--db2/btree/bt_conv.c22
-rw-r--r--db2/btree/bt_cursor.c76
-rw-r--r--db2/btree/bt_put.c4
-rw-r--r--db2/btree/bt_rec.c13
-rw-r--r--db2/btree/bt_recno.c38
-rw-r--r--db2/btree/btree.src8
-rw-r--r--db2/btree/btree_auto.c14
-rw-r--r--db2/clib/getlong.c1
-rw-r--r--db2/db.h16
-rw-r--r--db2/db/db.c73
-rw-r--r--db2/db/db_auto.c16
-rw-r--r--db2/db/db_conv.c68
-rw-r--r--db2/db/db_pr.c63
-rw-r--r--db2/db/db_ret.c9
-rw-r--r--db2/db/db_thread.c10
-rw-r--r--db2/db_185.h10
-rw-r--r--db2/db_int.h22
-rw-r--r--db2/hash/hash.c90
-rw-r--r--db2/hash/hash_auto.c14
-rw-r--r--db2/hash/hash_conv.c22
-rw-r--r--db2/hash/hash_dup.c49
-rw-r--r--db2/hash/hash_func.c6
-rw-r--r--db2/hash/hash_page.c69
-rw-r--r--db2/hash/hash_rec.c12
-rw-r--r--db2/include/btree.h8
-rw-r--r--db2/include/btree_ext.h2
-rw-r--r--db2/include/db.h.src17
-rw-r--r--db2/include/db_185.h.src10
-rw-r--r--db2/include/db_cxx.h10
-rw-r--r--db2/include/db_ext.h4
-rw-r--r--db2/include/db_int.h.src14
-rw-r--r--db2/include/db_page.h32
-rw-r--r--db2/include/db_shash.h22
-rw-r--r--db2/include/hash_ext.h3
-rw-r--r--db2/include/lock.h8
-rw-r--r--db2/include/log.h10
-rw-r--r--db2/include/log_ext.h6
-rw-r--r--db2/include/mp.h6
-rw-r--r--db2/include/shqueue.h37
-rw-r--r--db2/include/txn.h27
-rw-r--r--db2/lock/lock.c40
-rw-r--r--db2/lock/lock_deadlock.c9
-rw-r--r--db2/log/log.c104
-rw-r--r--db2/log/log_archive.c76
-rw-r--r--db2/log/log_auto.c4
-rw-r--r--db2/log/log_get.c9
-rw-r--r--db2/log/log_put.c23
-rw-r--r--db2/log/log_register.c11
-rw-r--r--db2/mp/mp_bh.c32
-rw-r--r--db2/mp/mp_fget.c10
-rw-r--r--db2/mp/mp_fopen.c78
-rw-r--r--db2/mp/mp_fput.c8
-rw-r--r--db2/mp/mp_fset.c4
-rw-r--r--db2/mp/mp_open.c41
-rw-r--r--db2/mutex/mutex.c2
-rw-r--r--db2/os/db_os_dir.c8
-rw-r--r--db2/progs/db_checkpoint/db_checkpoint.c25
-rw-r--r--db2/progs/db_deadlock/db_deadlock.c2
-rw-r--r--db2/progs/db_dump185/db_dump185.c4
-rw-r--r--db2/progs/db_load/db_load.c4
-rw-r--r--db2/progs/db_recover/db_recover.c3
-rw-r--r--db2/txn/txn.c195
-rw-r--r--db2/txn/txn_auto.c4
65 files changed, 924 insertions, 719 deletions
diff --git a/db2/Makefile b/db2/Makefile
index a75dc5aef1..e6b35aa51b 100644
--- a/db2/Makefile
+++ b/db2/Makefile
@@ -19,7 +19,7 @@
 #
 #	Sub-makefile for libdb.
 #
-#	The code is lifted straight from the db 2.3.6 distribution
+#	The code is lifted straight from the db 2.3.10 distribution
 #	with minimal changes.
 #
 
diff --git a/db2/btree/bt_close.c b/db2/btree/bt_close.c
index 7044599dd2..7dd7139c66 100644
--- a/db2/btree/bt_close.c
+++ b/db2/btree/bt_close.c
@@ -47,7 +47,7 @@
 #include "config.h"
 
 #ifndef lint
-static const char sccsid[] = "@(#)bt_close.c	10.23 (Sleepycat) 9/2/97";
+static const char sccsid[] = "@(#)bt_close.c	10.24 (Sleepycat) 9/17/97";
 #endif /* not lint */
 
 #ifndef NO_SYSTEM_INCLUDES
@@ -150,7 +150,7 @@ __bam_upstat(dbp)
 
 	/*
 	 * We use a no-op log call to log the update of the statistics onto the
-	 * metadata page.  The dbp->close() call isn't transaction protected to
+	 * metadata page.  The Db->close call isn't transaction protected to
 	 * start with, and I'm not sure what undoing a statistics update means,
 	 * anyway.
 	 */
diff --git a/db2/btree/bt_conv.c b/db2/btree/bt_conv.c
index c9d5d1bc3e..c89493cbed 100644
--- a/db2/btree/bt_conv.c
+++ b/db2/btree/bt_conv.c
@@ -8,7 +8,7 @@
 #include "config.h"
 
 #ifndef lint
-static const char sccsid[] = "@(#)bt_conv.c	10.4 (Sleepycat) 9/3/97";
+static const char sccsid[] = "@(#)bt_conv.c	10.5 (Sleepycat) 9/15/97";
 #endif /* not lint */
 
 #ifndef NO_SYSTEM_INCLUDES
@@ -21,12 +21,11 @@ static const char sccsid[] = "@(#)bt_conv.c	10.4 (Sleepycat) 9/3/97";
 #include "btree.h"
 
 /*
- * __bam_pgin, __bam_pgout --
- *	Convert host-specific page layout to/from the host-independent
- *	format stored on disk.
+ * __bam_pgin --
+ *	Convert host-specific page layout from the host-independent format
+ *	stored on disk.
  *
  * PUBLIC: int __bam_pgin __P((db_pgno_t, void *, DBT *));
- * PUBLIC: int __bam_pgout __P((db_pgno_t, void *, DBT *));
  */
 int
 __bam_pgin(pg, pp, cookie)
@@ -39,9 +38,17 @@ __bam_pgin(pg, pp, cookie)
 	pginfo = (DB_PGINFO *)cookie->data;
 	if (!pginfo->needswap)
 		return (0);
-	return (pg == PGNO_METADATA ? __bam_mswap(pp) : __db_pgin(pg, pp));
+	return (pg == PGNO_METADATA ?
+	    __bam_mswap(pp) : __db_pgin(pg, pginfo->db_pagesize, pp));
 }
 
+/*
+ * __bam_pgout --
+ *	Convert host-specific page layout to the host-independent format
+ *	stored on disk.
+ *
+ * PUBLIC: int __bam_pgout __P((db_pgno_t, void *, DBT *));
+ */
 int
 __bam_pgout(pg, pp, cookie)
 	db_pgno_t pg;
@@ -53,7 +60,8 @@ __bam_pgout(pg, pp, cookie)
 	pginfo = (DB_PGINFO *)cookie->data;
 	if (!pginfo->needswap)
 		return (0);
-	return (pg == PGNO_METADATA ? __bam_mswap(pp) : __db_pgout(pg, pp));
+	return (pg == PGNO_METADATA ?
+	    __bam_mswap(pp) : __db_pgout(pg, pginfo->db_pagesize, pp));
 }
 
 /*
diff --git a/db2/btree/bt_cursor.c b/db2/btree/bt_cursor.c
index efae556030..a1266bcd3c 100644
--- a/db2/btree/bt_cursor.c
+++ b/db2/btree/bt_cursor.c
@@ -8,7 +8,7 @@
 #include "config.h"
 
 #ifndef lint
-static const char sccsid[] = "@(#)bt_cursor.c	10.27 (Sleepycat) 9/3/97";
+static const char sccsid[] = "@(#)bt_cursor.c	10.33 (Sleepycat) 9/24/97";
 #endif /* not lint */
 
 #ifndef NO_SYSTEM_INCLUDES
@@ -81,7 +81,10 @@ __bam_cursor(dbp, txn, dbcp)
 	dbc->c_get = __bam_c_get;
 	dbc->c_put = __bam_c_put;
 
-	/* All cursor structures hang off the main DB structure. */
+	/*
+	 * All cursors are queued from the master DB structure.  Add the
+	 * cursor to that queue.
+	 */
 	DB_THREAD_LOCK(dbp);
 	TAILQ_INSERT_HEAD(&dbp->curs_queue, dbc, links);
 	DB_THREAD_UNLOCK(dbp);
@@ -99,31 +102,53 @@ __bam_c_close(dbc)
 	DBC *dbc;
 {
 	DB *dbp;
-	CURSOR *cp;
 	int ret;
 
 	DEBUG_LWRITE(dbc->dbp, dbc->txn, "bam_c_close", NULL, NULL, 0);
 
 	GETHANDLE(dbc->dbp, dbc->txn, &dbp, ret);
+
+	ret = __bam_c_iclose(dbp, dbc);
+
+	PUTHANDLE(dbp);
+	return (ret);
+}
+
+/*
+ * __bam_c_iclose --
+ *	Close a single cursor -- internal version.
+ *
+ * PUBLIC: int __bam_c_iclose __P((DB *, DBC *));
+ */
+int
+__bam_c_iclose(dbp, dbc)
+	DB *dbp;
+	DBC *dbc;
+{
+	CURSOR *cp;
+	int ret;
+
 	cp = dbc->internal;
 
-	/* If a cursor key was deleted do the actual deletion.  */
-	ret = F_ISSET(cp, C_DELETED) ?  __bam_c_physdel(dbp, cp, NULL) : 0;
+	/* If a cursor key was deleted, perform the actual deletion.  */
+	ret = F_ISSET(cp, C_DELETED) ? __bam_c_physdel(dbp, cp, NULL) : 0;
 
 	/* Discard any lock if we're not inside a transaction. */
-	if (dbp->txn == NULL && cp->lock != LOCK_INVALID)
+	if (cp->lock != LOCK_INVALID)
 		(void)__BT_TLPUT(dbp, cp->lock);
 
-	/* Remove the cursor from the queue. */
-	DB_THREAD_LOCK(dbp);
-	TAILQ_REMOVE(&dbp->curs_queue, dbc, links);
-	DB_THREAD_UNLOCK(dbp);
+	/*
+	 * All cursors are queued from the master DB structure.  Remove the
+	 * cursor from that queue.
+	 */
+	DB_THREAD_LOCK(dbc->dbp);
+	TAILQ_REMOVE(&dbc->dbp->curs_queue, dbc, links);
+	DB_THREAD_UNLOCK(dbc->dbp);
 
 	/* Discard the structures. */
-	FREE(cp, sizeof(CURSOR));
+	FREE(dbc->internal, sizeof(CURSOR));
 	FREE(dbc, sizeof(DBC));
 
-	PUTHANDLE(dbp);
 	return (ret);
 }
 
@@ -235,27 +260,22 @@ __bam_get(argdbp, txn, key, data, flags)
 	if ((ret = __db_getchk(argdbp, key, data, flags)) != 0)
 		return (ret);
 
-	/* Build a cursor. */
+	/* Build an internal cursor. */
 	memset(&cp, 0, sizeof(cp));
 	cp.dbc = &dbc;
 	cp.pgno = cp.dpgno = PGNO_INVALID;
 	cp.lock = LOCK_INVALID;
+	cp.flags = C_INTERNAL;
 
+	/* Build an external cursor. */
 	memset(&dbc, 0, sizeof(dbc));
 	dbc.dbp = argdbp;
 	dbc.txn = txn;
 	dbc.internal = &cp;
 
 	/* Get the key. */
-	if ((ret = __bam_c_get(&dbc,
-	    key, data, LF_ISSET(DB_SET_RECNO) ? DB_SET_RECNO : DB_SET)) != 0)
-		return (ret);
-
-	/* Discard any lock, the cursor didn't really exist. */
-	if (cp.lock != LOCK_INVALID)
-		(void)__BT_TLPUT(argdbp, cp.lock);
-
-	return (0);
+	return(__bam_c_get(&dbc,
+	    key, data, LF_ISSET(DB_SET_RECNO) ? DB_SET_RECNO : DB_SET));
 }
 
 /*
@@ -275,8 +295,7 @@ __bam_c_get(dbc, key, data, flags)
 	int exact, ret;
 
 	DEBUG_LREAD(dbc->dbp, dbc->txn, "bam_c_get",
-	    flags == DB_SET || flags == DB_SET_RANGE ? key : NULL,
-	    NULL, flags);
+	    flags == DB_SET || flags == DB_SET_RANGE ? key : NULL, NULL, flags);
 
 	cp = dbc->internal;
 
@@ -399,6 +418,10 @@ __bam_c_get(dbc, key, data, flags)
 	/* Release the pinned page. */
 	ret = memp_fput(dbp->mpf, cp->page, 0);
 
+	/* Internal cursors don't hold locks. */
+	if (F_ISSET(cp, C_INTERNAL) && cp->lock != LOCK_INVALID)
+		(void)__BT_TLPUT(dbp, cp->lock);
+
 	++t->lstat.bt_get;
 
 	if (0) {
@@ -864,7 +887,7 @@ __bam_c_prev(dbp, cp)
 	 * If at the beginning of the page, move to any previous one.
 	 *
 	 * !!!
-         * This code handles empty pages and pages with only deleted entries.
+	 * This code handles empty pages and pages with only deleted entries.
 	 */
 	for (;;) {
 		if (indx == 0) {
@@ -1472,8 +1495,7 @@ __bam_c_physdel(dbp, cp, h)
 		 *	empty the current page of duplicates, we don't need to
 		 *	touch the parent page.
 		 */
-		if (PREV_PGNO(h) != PGNO_INVALID ||
-		    (h != NULL && pgno == h->pgno))
+		if (prev_pgno != PGNO_INVALID || (h != NULL && pgno == h->pgno))
 			goto done;
 
 		/*
diff --git a/db2/btree/bt_put.c b/db2/btree/bt_put.c
index 0f0b1e7126..af09f76d41 100644
--- a/db2/btree/bt_put.c
+++ b/db2/btree/bt_put.c
@@ -47,7 +47,7 @@
 #include "config.h"
 
 #ifndef lint
-static const char sccsid[] = "@(#)bt_put.c	10.24 (Sleepycat) 9/3/97";
+static const char sccsid[] = "@(#)bt_put.c	10.25 (Sleepycat) 9/17/97";
 #endif /* not lint */
 
 #ifndef NO_SYSTEM_INCLUDES
@@ -99,7 +99,7 @@ __bam_put(argdbp, txn, key, data, flags)
 	t = dbp->internal;
 
 retry:	/*
-	 * Find the location at which to insert.  The call to bt_lookup()
+	 * Find the location at which to insert.  The call to __bam_lookup
 	 * leaves the returned page pinned.
 	 */
 	if ((ret = __bam_lookup(dbp, key, &exact)) != 0) {
diff --git a/db2/btree/bt_rec.c b/db2/btree/bt_rec.c
index 07a3d93c74..9aeb395f27 100644
--- a/db2/btree/bt_rec.c
+++ b/db2/btree/bt_rec.c
@@ -8,7 +8,7 @@
 #include "config.h"
 
 #ifndef lint
-static const char sccsid[] = "@(#)bt_rec.c	10.13 (Sleepycat) 9/3/97";
+static const char sccsid[] = "@(#)bt_rec.c	10.14 (Sleepycat) 9/6/97";
 #endif /* not lint */
 
 #ifndef NO_SYSTEM_INCLUDES
@@ -298,11 +298,10 @@ __bam_split_recover(logp, dbtp, lsnp, redo, info)
 			goto done;
 
 		/* Allocate and initialize new left/right child pages. */
-		if ((_lp = (PAGE *)malloc(file_dbp->pgsize)) == NULL)
-			goto nomem;
-		if ((_rp = (PAGE *)malloc(file_dbp->pgsize)) == NULL) {
-nomem:			__set_errno(ENOMEM);
-			__db_err(file_dbp->dbenv, "%s", strerror(errno));
+		if ((_lp = (PAGE *)malloc(file_dbp->pgsize)) == NULL ||
+		    (_rp = (PAGE *)malloc(file_dbp->pgsize)) == NULL) {
+			ret = ENOMEM;
+			__db_err(file_dbp->dbenv, "%s", strerror(ret));
 			goto out;
 		}
 		if (rootsplit) {
@@ -668,7 +667,7 @@ __bam_cadjust_recover(logp, dbtp, lsnp, redo, info)
 	REC_INTRO(__bam_cadjust_read);
 
 	if ((ret = memp_fget(mpf, &argp->pgno, 0, &pagep)) != 0) {
-		__set_errno(__db_pgerr(file_dbp, argp->pgno));
+		(void)__db_pgerr(file_dbp, argp->pgno);
 		pagep = NULL;
 		goto out;
 	}
diff --git a/db2/btree/bt_recno.c b/db2/btree/bt_recno.c
index 42ef9cc30d..f7c5cffdc6 100644
--- a/db2/btree/bt_recno.c
+++ b/db2/btree/bt_recno.c
@@ -8,7 +8,7 @@
 #include "config.h"
 
 #ifndef lint
-static const char sccsid[] = "@(#)bt_recno.c	10.15 (Sleepycat) 9/3/97";
+static const char sccsid[] = "@(#)bt_recno.c	10.19 (Sleepycat) 9/20/97";
 #endif /* not lint */
 
 #ifndef NO_SYSTEM_INCLUDES
@@ -76,7 +76,7 @@ __ram_open(dbp, type, dbinfo)
 
 	/* Allocate and initialize the private RECNO structure. */
 	if ((rp = (RECNO *)calloc(1, sizeof(*rp))) == NULL)
-		return (errno);
+		return (ENOMEM);
 
 	if (dbinfo != NULL) {
 		/*
@@ -150,7 +150,7 @@ err:	/* If we mmap'd a source file, discard it. */
 
 	/* If we allocated room for key/data return, discard it. */
 	t = dbp->internal;
-	if (t->bt_rkey.data != NULL)
+	if (t != NULL && t->bt_rkey.data != NULL)
 		free(t->bt_rkey.data);
 
 	FREE(rp, sizeof(*rp));
@@ -193,7 +193,10 @@ __ram_cursor(dbp, txn, dbcp)
 	dbc->c_get = __ram_c_get;
 	dbc->c_put = __ram_c_put;
 
-	/* All cursor structures hang off the main DB structure. */
+	/*
+	 * All cursors are queued from the master DB structure.  Add the
+	 * cursor to that queue.
+	 */
 	DB_THREAD_LOCK(dbp);
 	TAILQ_INSERT_HEAD(&dbp->curs_queue, dbc, links);
 	DB_THREAD_UNLOCK(dbp);
@@ -382,16 +385,29 @@ static int
 __ram_c_close(dbc)
 	DBC *dbc;
 {
-	DB *dbp;
-
 	DEBUG_LWRITE(dbc->dbp, dbc->txn, "ram_c_close", NULL, NULL, 0);
 
-	dbp = dbc->dbp;
+	return (__ram_c_iclose(dbc->dbp, dbc));
+}
 
-	/* Remove the cursor from the queue. */
-	DB_THREAD_LOCK(dbp);
-	TAILQ_REMOVE(&dbp->curs_queue, dbc, links);
-	DB_THREAD_UNLOCK(dbp);
+/*
+ * __ram_c_iclose --
+ *	Close a single cursor -- internal version.
+ *
+ * PUBLIC: int __ram_c_iclose __P((DB *, DBC *));
+ */
+int
+__ram_c_iclose(dbp, dbc)
+	DB *dbp;
+	DBC *dbc;
+{
+	/*
+	 * All cursors are queued from the master DB structure.  Remove the
+	 * cursor from that queue.
+	 */
+	DB_THREAD_LOCK(dbc->dbp);
+	TAILQ_REMOVE(&dbc->dbp->curs_queue, dbc, links);
+	DB_THREAD_UNLOCK(dbc->dbp);
 
 	/* Discard the structures. */
 	FREE(dbc->internal, sizeof(RCURSOR));
diff --git a/db2/btree/btree.src b/db2/btree/btree.src
index 50cc0dd0ff..7c8c4b125f 100644
--- a/db2/btree/btree.src
+++ b/db2/btree/btree.src
@@ -8,7 +8,7 @@
 #include "config.h"
 
 #ifndef lint
-static const char sccsid[] = "@(#)btree.src	10.3 (Sleepycat) 8/17/97";
+static const char sccsid[] = "@(#)btree.src	10.4 (Sleepycat) 8/27/97";
 #endif /* not lint */
 
 PREFIX	bam
@@ -88,7 +88,7 @@ END
 
 /*
  * BTREE-adj: used to log the adjustment of an index.
- * 
+ *
  * pgno:	the page modified.
  * lsn:		the page's original lsn.
  * indx:	the index adjusted.
@@ -106,7 +106,7 @@ END
 
 /*
  * BTREE-cadjust: used to adjust the count change in an internal page.
- * 
+ *
  * pgno:	the page modified.
  * lsn:		the page's original lsn.
  * indx:	the index to be adjusted.
@@ -124,7 +124,7 @@ END
 
 /*
  * BTREE-cdel: used to log the intent-to-delete of a cursor record.
- * 
+ *
  * pgno:	the page modified.
  * lsn:		the page's original lsn.
  * indx:	the index to be deleted.
diff --git a/db2/btree/btree_auto.c b/db2/btree/btree_auto.c
index e6b72252e5..353ee7bc27 100644
--- a/db2/btree/btree_auto.c
+++ b/db2/btree/btree_auto.c
@@ -119,7 +119,7 @@ __bam_pg_alloc_print(notused1, dbtp, lsnp, notused3, notused4)
 	notused3 = 0;
 	notused4 = NULL;
 
-	if((ret = __bam_pg_alloc_read(dbtp->data, &argp)) != 0)
+	if ((ret = __bam_pg_alloc_read(dbtp->data, &argp)) != 0)
 		return (ret);
 	printf("[%lu][%lu]bam_pg_alloc: rec: %lu txnid %lx prevlsn [%lu][%lu]\n",
 	    (u_long)lsnp->file,
@@ -284,7 +284,7 @@ __bam_pg_free_print(notused1, dbtp, lsnp, notused3, notused4)
 	notused3 = 0;
 	notused4 = NULL;
 
-	if((ret = __bam_pg_free_read(dbtp->data, &argp)) != 0)
+	if ((ret = __bam_pg_free_read(dbtp->data, &argp)) != 0)
 		return (ret);
 	printf("[%lu][%lu]bam_pg_free: rec: %lu txnid %lx prevlsn [%lu][%lu]\n",
 	    (u_long)lsnp->file,
@@ -479,7 +479,7 @@ __bam_split_print(notused1, dbtp, lsnp, notused3, notused4)
 	notused3 = 0;
 	notused4 = NULL;
 
-	if((ret = __bam_split_read(dbtp->data, &argp)) != 0)
+	if ((ret = __bam_split_read(dbtp->data, &argp)) != 0)
 		return (ret);
 	printf("[%lu][%lu]bam_split: rec: %lu txnid %lx prevlsn [%lu][%lu]\n",
 	    (u_long)lsnp->file,
@@ -672,7 +672,7 @@ __bam_rsplit_print(notused1, dbtp, lsnp, notused3, notused4)
 	notused3 = 0;
 	notused4 = NULL;
 
-	if((ret = __bam_rsplit_read(dbtp->data, &argp)) != 0)
+	if ((ret = __bam_rsplit_read(dbtp->data, &argp)) != 0)
 		return (ret);
 	printf("[%lu][%lu]bam_rsplit: rec: %lu txnid %lx prevlsn [%lu][%lu]\n",
 	    (u_long)lsnp->file,
@@ -848,7 +848,7 @@ __bam_adj_print(notused1, dbtp, lsnp, notused3, notused4)
 	notused3 = 0;
 	notused4 = NULL;
 
-	if((ret = __bam_adj_read(dbtp->data, &argp)) != 0)
+	if ((ret = __bam_adj_read(dbtp->data, &argp)) != 0)
 		return (ret);
 	printf("[%lu][%lu]bam_adj: rec: %lu txnid %lx prevlsn [%lu][%lu]\n",
 	    (u_long)lsnp->file,
@@ -1007,7 +1007,7 @@ __bam_cadjust_print(notused1, dbtp, lsnp, notused3, notused4)
 	notused3 = 0;
 	notused4 = NULL;
 
-	if((ret = __bam_cadjust_read(dbtp->data, &argp)) != 0)
+	if ((ret = __bam_cadjust_read(dbtp->data, &argp)) != 0)
 		return (ret);
 	printf("[%lu][%lu]bam_cadjust: rec: %lu txnid %lx prevlsn [%lu][%lu]\n",
 	    (u_long)lsnp->file,
@@ -1157,7 +1157,7 @@ __bam_cdel_print(notused1, dbtp, lsnp, notused3, notused4)
 	notused3 = 0;
 	notused4 = NULL;
 
-	if((ret = __bam_cdel_read(dbtp->data, &argp)) != 0)
+	if ((ret = __bam_cdel_read(dbtp->data, &argp)) != 0)
 		return (ret);
 	printf("[%lu][%lu]bam_cdel: rec: %lu txnid %lx prevlsn [%lu][%lu]\n",
 	    (u_long)lsnp->file,
diff --git a/db2/clib/getlong.c b/db2/clib/getlong.c
index 0cc8567081..85f4e8c9e2 100644
--- a/db2/clib/getlong.c
+++ b/db2/clib/getlong.c
@@ -18,7 +18,6 @@ static const char sccsid[] = "@(#)getlong.c	10.2 (Sleepycat) 5/1/97";
 #endif
 
 #include "db.h"
-#include "db_int.h"
 #include "clib_ext.h"
 
 /*
diff --git a/db2/db.h b/db2/db.h
index c80d8e3633..6911002ed5 100644
--- a/db2/db.h
+++ b/db2/db.h
@@ -4,7 +4,7 @@
  * Copyright (c) 1996, 1997
  *	Sleepycat Software.  All rights reserved.
  *
- *	@(#)db.h.src	10.71 (Sleepycat) 9/4/97
+ *	@(#)db.h.src	10.77 (Sleepycat) 9/24/97
  */
 
 #ifndef _DB_H_
@@ -67,8 +67,8 @@
 
 #define	DB_VERSION_MAJOR	2
 #define	DB_VERSION_MINOR	3
-#define	DB_VERSION_PATCH	6
-#define	DB_VERSION_STRING	"Sleepycat Software: DB 2.3.6: (9/4/97)"
+#define	DB_VERSION_PATCH	10
+#define	DB_VERSION_STRING	"Sleepycat Software: DB 2.3.10: (9/24/97)"
 
 typedef	u_int32_t	db_pgno_t;	/* Page number type. */
 typedef	u_int16_t	db_indx_t;	/* Page offset type. */
@@ -339,7 +339,7 @@ struct __db_ilock {			/* Internal DB access method lock. */
 
 /* DB access method description structure. */
 struct __db {
-	void	*mutex;			/* Synchronization for free threading */
+	void	*mutexp;		/* Synchronization for free threading */
 	DBTYPE	 type;			/* DB access method. */
 	DB_ENV	*dbenv;			/* DB_ENV structure. */
 	DB_ENV	*mp_dbenv;		/* DB_ENV for local mpool creation. */
@@ -641,11 +641,11 @@ extern "C" {
 #endif
 int	memp_close __P((DB_MPOOL *));
 int	memp_fclose __P((DB_MPOOLFILE *));
-int	memp_fget __P((DB_MPOOLFILE *, db_pgno_t *, unsigned long, void *));
+int	memp_fget __P((DB_MPOOLFILE *, db_pgno_t *, int, 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 *, unsigned long));
-int	memp_fset __P((DB_MPOOLFILE *, void *, unsigned long));
+int	memp_fput __P((DB_MPOOLFILE *, void *, int));
+int	memp_fset __P((DB_MPOOLFILE *, void *, int));
 int	memp_fsync __P((DB_MPOOLFILE *));
 int	memp_open __P((const char *, int, int, DB_ENV *, DB_MPOOL **));
 int	memp_register __P((DB_MPOOL *, int,
@@ -698,7 +698,7 @@ 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 *, long, long));
+int	  txn_checkpoint __P((const DB_TXNMGR *, int, int));
 int	  txn_commit __P((DB_TXN *));
 int	  txn_close __P((DB_TXNMGR *));
 u_int32_t txn_id __P((DB_TXN *));
diff --git a/db2/db/db.c b/db2/db/db.c
index 8dad5febe8..9ebe73cf6e 100644
--- a/db2/db/db.c
+++ b/db2/db/db.c
@@ -44,7 +44,7 @@
 #include "config.h"
 
 #ifndef lint
-static const char sccsid[] = "@(#)db.c	10.38 (Sleepycat) 9/2/97";
+static const char sccsid[] = "@(#)db.c	10.41 (Sleepycat) 9/23/97";
 #endif /* not lint */
 
 #ifndef NO_SYSTEM_INCLUDES
@@ -137,7 +137,13 @@ db_open(fname, type, flags, mode, dbenv, dbinfo, dbpp)
 	}
 	dbp->dbenv = dbenv;
 
-	/* Convert the dbinfo flags. */
+	/* Convert the db_open(3) flags. */
+	if (LF_ISSET(DB_RDONLY))
+		F_SET(dbp, DB_AM_RDONLY);
+	if (LF_ISSET(DB_THREAD))
+		F_SET(dbp, DB_AM_THREAD);
+
+	/* Convert the dbinfo structure flags. */
 	if (dbinfo != NULL) {
 		/*
 		 * !!!
@@ -160,23 +166,6 @@ db_open(fname, type, flags, mode, dbenv, dbinfo, dbpp)
 			F_SET(dbp, DB_RE_SNAPSHOT);
 	}
 
-	/* Set based on the open(2) flags. */
-	if (LF_ISSET(DB_RDONLY))
-		F_SET(dbp, DB_AM_RDONLY);
-
-	/* Check threading fields. */
-	if (LF_ISSET(DB_THREAD)) {
-		if ((dbp->mutex =
-		    (db_mutex_t *)malloc(sizeof(db_mutex_t))) == NULL) {
-			__db_err(dbenv, "%s", strerror(ENOMEM));
-			ret = ENOMEM;
-			goto err;
-		}
-		__db_mutex_init(dbp->mutex, 0);
-
-		F_SET(dbp, DB_AM_THREAD);
-	}
-
 	/*
 	 * Always set the master and initialize the queues, so we can
 	 * use these fields without checking the thread bit.
@@ -190,7 +179,7 @@ db_open(fname, type, flags, mode, dbenv, dbinfo, dbpp)
 	 * Set based on the dbenv fields, although no logging or transactions
 	 * are possible for temporary files.
 	 */
-	if (dbp->dbenv != NULL) {
+	if (dbenv != NULL) {
 		if (dbenv->lk_info != NULL)
 			F_SET(dbp, DB_AM_LOCKING);
 		if (fname != NULL && dbenv->lg_info != NULL)
@@ -274,8 +263,8 @@ open_retry:	if (LF_ISSET(DB_CREATE)) {
 		 * sizes, we limit the default pagesize to 16K.
 		 */
 		if (dbp->pgsize == 0) {
-			if ((ret = __db_stat(dbp->dbenv,
-			    real_name, fd, NULL, &io)) != 0)
+			if ((ret =
+			    __db_stat(dbenv, real_name, fd, NULL, &io)) != 0)
 				goto err;
 			if (io < 512)
 				io = 512;
@@ -573,6 +562,15 @@ empty:	/*
 	    0, &pgcookie, dbp->lock.fileid, &dbp->mpf)) != 0)
 		goto err;
 
+	/*
+	 * XXX
+	 * Truly spectacular layering violation.  We need a per-thread mutex
+	 * that lives in shared memory (thanks, HP-UX!) and so we acquire a
+	 * pointer to the mpool one.
+	 */
+	if (F_ISSET(dbp, DB_AM_THREAD))
+		dbp->mutexp = dbp->mpf->mutexp;
+
 	/* Get a log file id. */
 	if (F_ISSET(dbp, DB_AM_LOGGING) &&
 	    (ret = log_register(dbenv->lg_info,
@@ -672,7 +670,9 @@ db_close(dbp, flags)
 	DB *tdbp;
 	int ret, t_ret;
 
-	ret = 0;
+	/* Validate arguments. */
+	if ((ret = __db_fchk(dbp->dbenv, "db_close", flags, DB_NOSYNC)) != 0)
+		return (ret);
 
 	/* Sync the underlying file. */
 	if (!LF_ISSET(DB_NOSYNC) &&
@@ -685,10 +685,26 @@ db_close(dbp, flags)
 	 */
 	for (tdbp = LIST_FIRST(&dbp->handleq);
 	    tdbp != NULL; tdbp = LIST_NEXT(tdbp, links)) {
-
 		while ((dbc = TAILQ_FIRST(&tdbp->curs_queue)) != NULL)
-			if ((t_ret = dbc->c_close(dbc)) != 0 && ret == 0)
-				ret = t_ret;
+			switch (tdbp->type) {
+			case DB_BTREE:
+				if ((t_ret =
+				    __bam_c_iclose(tdbp, dbc)) != 0 && ret == 0)
+					ret = t_ret;
+				break;
+			case DB_HASH:
+				if ((t_ret =
+				    __ham_c_iclose(tdbp, dbc)) != 0 && ret == 0)
+					ret = t_ret;
+				break;
+			case DB_RECNO:
+				if ((t_ret =
+				    __ram_c_iclose(tdbp, dbc)) != 0 && ret == 0)
+					ret = t_ret;
+				break;
+			default:
+				abort();
+			}
 
 		switch (tdbp->type) {
 		case DB_BTREE:
@@ -706,7 +722,6 @@ db_close(dbp, flags)
 		default:
 			abort();
 		}
-
 	}
 
 	/* Sync the memory pool. */
@@ -722,10 +737,6 @@ db_close(dbp, flags)
 	    (t_ret = memp_close(dbp->mp)) != 0 && ret == 0)
 		ret = t_ret;
 
-	/* Discard the mutex. */
-	if (dbp->mutex != NULL)
-		FREE(dbp->mutex, sizeof(db_mutex_t));
-
 	/* Discard the log file id. */
 	if (F_ISSET(dbp, DB_AM_LOGGING))
 		(void)log_unregister(dbp->dbenv->lg_info, dbp->log_fileid);
diff --git a/db2/db/db_auto.c b/db2/db/db_auto.c
index 4684f1a39f..6922504383 100644
--- a/db2/db/db_auto.c
+++ b/db2/db/db_auto.c
@@ -141,7 +141,7 @@ __db_addrem_print(notused1, dbtp, lsnp, notused3, notused4)
 	notused3 = 0;
 	notused4 = NULL;
 
-	if((ret = __db_addrem_read(dbtp->data, &argp)) != 0)
+	if ((ret = __db_addrem_read(dbtp->data, &argp)) != 0)
 		return (ret);
 	printf("[%lu][%lu]db_addrem: rec: %lu txnid %lx prevlsn [%lu][%lu]\n",
 	    (u_long)lsnp->file,
@@ -331,7 +331,7 @@ __db_split_print(notused1, dbtp, lsnp, notused3, notused4)
 	notused3 = 0;
 	notused4 = NULL;
 
-	if((ret = __db_split_read(dbtp->data, &argp)) != 0)
+	if ((ret = __db_split_read(dbtp->data, &argp)) != 0)
 		return (ret);
 	printf("[%lu][%lu]db_split: rec: %lu txnid %lx prevlsn [%lu][%lu]\n",
 	    (u_long)lsnp->file,
@@ -526,7 +526,7 @@ __db_big_print(notused1, dbtp, lsnp, notused3, notused4)
 	notused3 = 0;
 	notused4 = NULL;
 
-	if((ret = __db_big_read(dbtp->data, &argp)) != 0)
+	if ((ret = __db_big_read(dbtp->data, &argp)) != 0)
 		return (ret);
 	printf("[%lu][%lu]db_big: rec: %lu txnid %lx prevlsn [%lu][%lu]\n",
 	    (u_long)lsnp->file,
@@ -693,7 +693,7 @@ __db_ovref_print(notused1, dbtp, lsnp, notused3, notused4)
 	notused3 = 0;
 	notused4 = NULL;
 
-	if((ret = __db_ovref_read(dbtp->data, &argp)) != 0)
+	if ((ret = __db_ovref_read(dbtp->data, &argp)) != 0)
 		return (ret);
 	printf("[%lu][%lu]db_ovref: rec: %lu txnid %lx prevlsn [%lu][%lu]\n",
 	    (u_long)lsnp->file,
@@ -854,7 +854,7 @@ __db_relink_print(notused1, dbtp, lsnp, notused3, notused4)
 	notused3 = 0;
 	notused4 = NULL;
 
-	if((ret = __db_relink_read(dbtp->data, &argp)) != 0)
+	if ((ret = __db_relink_read(dbtp->data, &argp)) != 0)
 		return (ret);
 	printf("[%lu][%lu]db_relink: rec: %lu txnid %lx prevlsn [%lu][%lu]\n",
 	    (u_long)lsnp->file,
@@ -1017,7 +1017,7 @@ __db_addpage_print(notused1, dbtp, lsnp, notused3, notused4)
 	notused3 = 0;
 	notused4 = NULL;
 
-	if((ret = __db_addpage_read(dbtp->data, &argp)) != 0)
+	if ((ret = __db_addpage_read(dbtp->data, &argp)) != 0)
 		return (ret);
 	printf("[%lu][%lu]db_addpage: rec: %lu txnid %lx prevlsn [%lu][%lu]\n",
 	    (u_long)lsnp->file,
@@ -1192,7 +1192,7 @@ __db_debug_print(notused1, dbtp, lsnp, notused3, notused4)
 	notused3 = 0;
 	notused4 = NULL;
 
-	if((ret = __db_debug_read(dbtp->data, &argp)) != 0)
+	if ((ret = __db_debug_read(dbtp->data, &argp)) != 0)
 		return (ret);
 	printf("[%lu][%lu]db_debug: rec: %lu txnid %lx prevlsn [%lu][%lu]\n",
 	    (u_long)lsnp->file,
@@ -1347,7 +1347,7 @@ __db_noop_print(notused1, dbtp, lsnp, notused3, notused4)
 	notused3 = 0;
 	notused4 = NULL;
 
-	if((ret = __db_noop_read(dbtp->data, &argp)) != 0)
+	if ((ret = __db_noop_read(dbtp->data, &argp)) != 0)
 		return (ret);
 	printf("[%lu][%lu]db_noop: rec: %lu txnid %lx prevlsn [%lu][%lu]\n",
 	    (u_long)lsnp->file,
diff --git a/db2/db/db_conv.c b/db2/db/db_conv.c
index 6608005b66..8eccc2e602 100644
--- a/db2/db/db_conv.c
+++ b/db2/db/db_conv.c
@@ -44,7 +44,7 @@
 #include "config.h"
 
 #ifndef lint
-static const char sccsid[] = "@(#)db_conv.c	10.5 (Sleepycat) 9/3/97";
+static const char sccsid[] = "@(#)db_conv.c	10.7 (Sleepycat) 9/21/97";
 #endif /* not lint */
 
 #ifndef NO_SYSTEM_INCLUDES
@@ -58,28 +58,34 @@ static const char sccsid[] = "@(#)db_conv.c	10.5 (Sleepycat) 9/3/97";
 #include "db_swap.h"
 #include "db_am.h"
 
-static int __db_convert __P((db_pgno_t, void *, int));
+static int __db_convert __P((db_pgno_t, void *, size_t, int));
 
 /*
- * __db_pgin, __db_pgout --
+ * __db_pgin --
  *
- * PUBLIC: int __db_pgin __P((db_pgno_t, void *));
- * PUBLIC: int __db_pgout __P((db_pgno_t, void *));
+ * PUBLIC: int __db_pgin __P((db_pgno_t, size_t, void *));
  */
 int
-__db_pgin(pg, pp)
+__db_pgin(pg, pagesize, pp)
 	db_pgno_t pg;
+	size_t pagesize;
 	void *pp;
 {
-	return (__db_convert(pg, pp, 1));
+	return (__db_convert(pg, pp, pagesize, 1));
 }
 
+/*
+ * __db_pgout --
+ *
+ * PUBLIC: int __db_pgout __P((db_pgno_t, size_t, void *));
+ */
 int
-__db_pgout(pg, pp)
+__db_pgout(pg, pagesize, pp)
 	db_pgno_t pg;
+	size_t pagesize;
 	void *pp;
 {
-	return (__db_convert(pg, pp, 0));
+	return (__db_convert(pg, pp, pagesize, 0));
 }
 
 /*
@@ -87,19 +93,19 @@ __db_pgout(pg, pp)
  *	Actually convert a page.
  */
 static int
-__db_convert(pg, pp, pgin)
+__db_convert(pg, pp, pagesize, pgin)
 	db_pgno_t pg;			/* Unused, but left for the future. */
 	void *pp;
+	size_t pagesize;
 	int pgin;
 {
 	BINTERNAL *bi;
 	BKEYDATA *bk;
 	BOVERFLOW *bo;
-	HKEYDATA *hk;
 	PAGE *h;
 	RINTERNAL *ri;
-	db_indx_t i;
-	u_int8_t *p;
+	db_indx_t i, len, tmp;
+	u_int8_t *p, *end;
 
 	h = pp;
 	if (pgin) {
@@ -118,24 +124,42 @@ __db_convert(pg, pp, pgin)
 			if (pgin)
 				M_16_SWAP(h->inp[i]);
 
-			hk = GET_HKEYDATA(h, i);
-			switch (hk->type) {
+			switch (HPAGE_TYPE(h, i)) {
 			case H_KEYDATA:
 				break;
 			case H_DUPLICATE:
+				len = LEN_HKEYDATA(h, pagesize, i);
+				p = HKEYDATA_DATA(P_ENTRY(h, i));
+				for (end = p + len; p < end;) {
+					if (pgin) {
+						P_16_SWAP(p);
+						memcpy(&tmp,
+						    p, sizeof(db_indx_t));
+						p += sizeof(db_indx_t);
+					} else {
+						memcpy(&tmp,
+						    p, sizeof(db_indx_t));
+						SWAP16(p);
+					}
+					p += tmp;
+					SWAP16(p);
+				}
+				break;
+			case H_OFFDUP:
+				p = HOFFPAGE_PGNO(P_ENTRY(h, i));
+				SWAP32(p);			/* pgno */
+				break;
 			case H_OFFPAGE:
-				p = (u_int8_t *)hk + sizeof(u_int8_t);
-				++p;
-				SWAP32(p);			/* tlen */
+				p = HOFFPAGE_PGNO(P_ENTRY(h, i));
 				SWAP32(p);			/* pgno */
-				SWAP16(p);			/* offset */
-				SWAP16(p);			/* len */
+				SWAP32(p);			/* tlen */
 				break;
 			}
 
-			if (!pgin)
-				M_16_SWAP(h->inp[i]);
 		}
+		if (!pgin)
+			for (i = 0; i < NUM_ENT(h); i++)
+				M_16_SWAP(h->inp[i]);
 		break;
 	case P_LBTREE:
 	case P_LRECNO:
diff --git a/db2/db/db_pr.c b/db2/db/db_pr.c
index f86fd6770a..09d8057da4 100644
--- a/db2/db/db_pr.c
+++ b/db2/db/db_pr.c
@@ -8,7 +8,7 @@
 #include "config.h"
 
 #ifndef lint
-static const char sccsid[] = "@(#)db_pr.c	10.16 (Sleepycat) 9/3/97";
+static const char sccsid[] = "@(#)db_pr.c	10.17 (Sleepycat) 9/15/97";
 #endif /* not lint */
 
 #ifndef NO_SYSTEM_INCLUDES
@@ -184,7 +184,7 @@ __db_prbtree(dbp)
 	BTMETA *mp;
 	BTREE *t;
 	DB_LOCK lock;
-	EPG *sp;
+	EPG *epg;
 	FILE *fp;
 	RECNO *rp;
 	db_pgno_t i;
@@ -230,8 +230,8 @@ __db_prbtree(dbp)
 		    (u_long)rp->re_emap, (u_long)rp->re_msize);
 	}
 	(void)fprintf(fp, "stack:");
-	for (sp = t->bt_stack; sp < t->bt_sp; ++sp)
-		(void)fprintf(fp, " %lu", (u_long)sp->page->pgno);
+	for (epg = t->bt_stack; epg < t->bt_sp; ++epg)
+		(void)fprintf(fp, " %lu", (u_long)epg->page->pgno);
 	(void)fprintf(fp, "\n");
 	(void)fprintf(fp, "ovflsize: %lu\n", (u_long)t->bt_ovflsize);
 	(void)fflush(fp);
@@ -367,20 +367,15 @@ __db_prpage(h, all)
 {
 	BINTERNAL *bi;
 	BKEYDATA *bk;
-	HKEYDATA *hkd;
 	HOFFPAGE a_hkd;
 	FILE *fp;
 	RINTERNAL *ri;
 	db_indx_t dlen, len, i;
 	db_pgno_t pgno;
-	u_int8_t *p;
 	int deleted, ret;
 	const char *s;
-
-	bi = NULL;				/* XXX: Shut the compiler up. */
-	bk = NULL;
-	hkd = NULL;
-	ri = NULL;
+	u_int8_t *ep, *hk, *p;
+	void *sp;
 
 	fp = __db_prinit(NULL);
 
@@ -450,22 +445,18 @@ __db_prpage(h, all)
 		deleted = 0;
 		switch (TYPE(h)) {
 		case P_HASH:
-			hkd = GET_HKEYDATA(h, i);
-			break;
 		case P_IBTREE:
-			bi = GET_BINTERNAL(h, i);
-			break;
 		case P_IRECNO:
-			ri = GET_RINTERNAL(h, i);
+			sp = P_ENTRY(h, i);
 			break;
 		case P_LBTREE:
-			bk = GET_BKEYDATA(h, i);
+			sp = P_ENTRY(h, i);
 			deleted = i % 2 == 0 &&
 			    B_DISSET(GET_BKEYDATA(h, i + O_INDX)->type);
 			break;
 		case P_LRECNO:
 		case P_DUPLICATE:
-			bk = GET_BKEYDATA(h, i);
+			sp = P_ENTRY(h, i);
 			deleted = B_DISSET(GET_BKEYDATA(h, i)->type);
 			break;
 		default:
@@ -478,11 +469,11 @@ __db_prpage(h, all)
 		    deleted ? "D" : " ", (u_long)i, (u_long)h->inp[i]);
 		switch (TYPE(h)) {
 		case P_HASH:
-			switch (hkd->type) {
+			hk = sp;
+			switch (HPAGE_PTYPE(hk)) {
 			case H_OFFDUP:
 				memcpy(&pgno,
-				    (u_int8_t *)hkd + SSZ(HOFFDUP, pgno),
-				    sizeof(db_pgno_t));
+				    HOFFDUP_PGNO(hk), sizeof(db_pgno_t));
 				fprintf(fp,
 				    "%4lu [offpage dups]\n", (u_long)pgno);
 				break;
@@ -499,7 +490,8 @@ __db_prpage(h, all)
 					len = 1;
 
 				fprintf(fp, "Duplicates:\n");
-				for (p = hkd->data; p < hkd->data + len;) {
+				for (p = HKEYDATA_DATA(hk),
+				    ep = p + len; p < ep;) {
 					memcpy(&dlen, p, sizeof(db_indx_t));
 					p += sizeof(db_indx_t);
 					fprintf(fp, "\t\t");
@@ -509,13 +501,13 @@ __db_prpage(h, all)
 				break;
 			case H_KEYDATA:
 				if (i != 0)
-					__db_pr(hkd->data,
+					__db_pr(HKEYDATA_DATA(hk),
 					    LEN_HKEYDATA(h, 0, i));
 				else
-					fprintf(fp, "%s\n", hkd->data);
+					fprintf(fp, "%s\n", HKEYDATA_DATA(hk));
 				break;
 			case H_OFFPAGE:
-				memcpy(&a_hkd, hkd, HOFFPAGE_SIZE);
+				memcpy(&a_hkd, hk, HOFFPAGE_SIZE);
 				fprintf(fp,
 				    "overflow: total len: %4lu page: %4lu\n",
 				    (u_long)a_hkd.tlen, (u_long)a_hkd.pgno);
@@ -523,6 +515,7 @@ __db_prpage(h, all)
 			}
 			break;
 		case P_IBTREE:
+			bi = sp;
 			fprintf(fp, "count: %4lu pgno: %4lu ",
 			    (u_long)bi->nrecs, (u_long)bi->pgno);
 			switch (B_TYPE(bi->type)) {
@@ -541,12 +534,14 @@ __db_prpage(h, all)
 			}
 			break;
 		case P_IRECNO:
+			ri = sp;
 			fprintf(fp, "entries %4lu pgno %4lu\n",
 			    (u_long)ri->nrecs, (u_long)ri->pgno);
 			break;
 		case P_LBTREE:
 		case P_LRECNO:
 		case P_DUPLICATE:
+			bk = sp;
 			switch (B_TYPE(bk->type)) {
 			case B_KEYDATA:
 				__db_pr(bk->data, bk->len);
@@ -582,13 +577,9 @@ __db_isbad(h, die)
 {
 	BINTERNAL *bi;
 	BKEYDATA *bk;
-	HKEYDATA *hkd;
 	FILE *fp;
 	db_indx_t i;
-
-	bi = NULL;				/* XXX: Shut the compiler up. */
-	bk = NULL;
-	hkd = NULL;
+	int type;
 
 	fp = __db_prinit(NULL);
 
@@ -618,13 +609,13 @@ __db_isbad(h, die)
 		}
 		switch (TYPE(h)) {
 		case P_HASH:
-			hkd = GET_HKEYDATA(h, i);
-			if (hkd->type != H_OFFDUP &&
-			    hkd->type != H_DUPLICATE &&
-			    hkd->type != H_KEYDATA &&
-			    hkd->type != H_OFFPAGE) {
+			type = HPAGE_TYPE(h, i);
+			if (type != H_OFFDUP &&
+			    type != H_DUPLICATE &&
+			    type != H_KEYDATA &&
+			    type != H_OFFPAGE) {
 				fprintf(fp, "ILLEGAL HASH TYPE: %lu\n",
-				    (u_long)hkd->type);
+				    (u_long)type);
 				goto bad;
 			}
 			break;
diff --git a/db2/db/db_ret.c b/db2/db/db_ret.c
index baf0665446..ee2bc82f87 100644
--- a/db2/db/db_ret.c
+++ b/db2/db/db_ret.c
@@ -8,7 +8,7 @@
 #include "config.h"
 
 #ifndef lint
-static const char sccsid[] = "@(#)db_ret.c	10.6 (Sleepycat) 9/3/97";
+static const char sccsid[] = "@(#)db_ret.c	10.7 (Sleepycat) 9/15/97";
 #endif /* not lint */
 
 #ifndef NO_SYSTEM_INCLUDES
@@ -46,18 +46,19 @@ __db_ret(dbp, h, indx, dbt, memp, memsize)
 	HOFFPAGE ho;
 	BOVERFLOW *bo;
 	u_int32_t len;
-	void *data, *hk;
+	u_int8_t *hk;
+	void *data;
 
 	switch (TYPE(h)) {
 	case P_HASH:
 		hk = P_ENTRY(h, indx);
-		if (((HKEYDATA *)hk)->type == H_OFFPAGE) {
+		if (HPAGE_PTYPE(hk) == H_OFFPAGE) {
 			memcpy(&ho, hk, sizeof(HOFFPAGE));
 			return (__db_goff(dbp, dbt,
 			    ho.tlen, ho.pgno, memp, memsize));
 		}
 		len = LEN_HKEYDATA(h, dbp->pgsize, indx);
-		data = ((HKEYDATA *)hk)->data;
+		data = HKEYDATA_DATA(hk);
 		break;
 	case P_DUPLICATE:
 	case P_LBTREE:
diff --git a/db2/db/db_thread.c b/db2/db/db_thread.c
index e956e809d9..170baf5345 100644
--- a/db2/db/db_thread.c
+++ b/db2/db/db_thread.c
@@ -8,7 +8,7 @@
 #include "config.h"
 
 #ifndef lint
-static const char sccsid[] = "@(#)db_thread.c	8.11 (Sleepycat) 8/18/97";
+static const char sccsid[] = "@(#)db_thread.c	8.12 (Sleepycat) 9/23/97";
 #endif /* not lint */
 
 #ifndef NO_SYSTEM_INCLUDES
@@ -42,7 +42,7 @@ __db_gethandle(dbp, am_func, dbpp)
 	DB *ret_dbp;
 	int ret, t_ret;
 
-	if ((ret = __db_mutex_lock((db_mutex_t *)dbp->mutex, -1,
+	if ((ret = __db_mutex_lock((db_mutex_t *)dbp->mutexp, -1,
 	    dbp->dbenv == NULL ? NULL : dbp->dbenv->db_yield)) != 0)
 		return (ret);
 
@@ -75,7 +75,7 @@ err:		if (ret_dbp != NULL)
 			FREE(ret_dbp, sizeof(*ret_dbp));
 	}
 	if ((t_ret =
-	    __db_mutex_unlock((db_mutex_t *)dbp->mutex, -1)) != 0 && ret == 0)
+	    __db_mutex_unlock((db_mutex_t *)dbp->mutexp, -1)) != 0 && ret == 0)
 		ret = t_ret;
 	return (ret);
 }
@@ -94,13 +94,13 @@ __db_puthandle(dbp)
 	int ret;
 
 	master = dbp->master;
-	if ((ret = __db_mutex_lock((db_mutex_t *)master->mutex, -1,
+	if ((ret = __db_mutex_lock((db_mutex_t *)master->mutexp, -1,
 	    dbp->dbenv == NULL ? NULL : dbp->dbenv->db_yield)) != 0)
 		return (ret);
 
 	LIST_INSERT_HEAD(&master->handleq, dbp, links);
 
-	return (__db_mutex_unlock((db_mutex_t *)master->mutex, -1));
+	return (__db_mutex_unlock((db_mutex_t *)master->mutexp, -1));
 }
 
 /*
diff --git a/db2/db_185.h b/db2/db_185.h
index 650d365a60..b6a4d0a12a 100644
--- a/db2/db_185.h
+++ b/db2/db_185.h
@@ -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.3 (Sleepycat) 7/27/97
+ *	@(#)db_185.h.src	8.4 (Sleepycat) 9/16/97
  */
 
 #ifndef _DB_185_H_
@@ -72,6 +72,14 @@
 
 #endif
 
+/*
+ * XXX
+ * SGI/IRIX already has a pgno_t.
+ */
+#ifdef sgi
+#define        pgno_t  db_pgno_t
+#endif
+
 #define	MAX_PAGE_NUMBER	0xffffffff	/* >= # of pages in a file */
 typedef u_int32_t	pgno_t;
 #define	MAX_PAGE_OFFSET	65535		/* >= # of bytes in a page */
diff --git a/db2/db_int.h b/db2/db_int.h
index a088c693a8..56dfddb73f 100644
--- a/db2/db_int.h
+++ b/db2/db_int.h
@@ -4,7 +4,7 @@
  * Copyright (c) 1996, 1997
  *	Sleepycat Software.  All rights reserved.
  *
- *	@(#)db_int.h.src	10.28 (Sleepycat) 8/20/97
+ *	@(#)db_int.h.src	10.30 (Sleepycat) 9/23/97
  */
 
 #ifndef _DB_INTERNAL_H_
@@ -25,12 +25,6 @@
 
 #define	DB_MINCACHE	10		/* Minimum cached pages */
 
-/* Handle `errno' in the presence of multi-threading correctly.  On some
-   systems we need a special macro to do this right.  */
-#ifndef __set_errno
-# define __set_errno(val) (errno) = (val)
-#endif
-
 /*
  * Aligning items to particular sizes or in pages or memory.  ALIGNP is a
  * separate macro, as we've had to cast the pointer to different integral
@@ -94,7 +88,7 @@
 
 /* Structure used to print flag values. */
 typedef struct __fn {
-	u_int32_t mask;			/* Flag value. */
+	u_int32_t   mask;		/* Flag value. */
 	const char *name;		/* Flag name. */
 } FN;
 
@@ -183,11 +177,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)->mutex,  -1,		\
+	    __db_mutex_lock((db_mutex_t *)(dbp)->mutexp,  -1,		\
 	        (dbp)->dbenv == NULL ? NULL : (dbp)->dbenv->db_yield) : 0)
 #define	DB_THREAD_UNLOCK(dbp)						\
 	(F_ISSET(dbp, DB_AM_THREAD) ?					\
-	    __db_mutex_unlock((db_mutex_t *)(dbp)->mutex,  -1) : 0)
+	    __db_mutex_unlock((db_mutex_t *)(dbp)->mutexp,  -1) : 0)
 
 /* Btree/recno local statistics structure. */
 struct __db_bt_lstat;	typedef struct __db_bt_lstat DB_BTREE_LSTAT;
@@ -312,14 +306,6 @@ typedef struct __dbpginfo {
  * Transactions and recovery.
  *******************************************************/
 /*
- * The locker id space is divided between the transaction manager and the lock
- * manager.  Lockid's start at 0 and go to MAX_LOCKER_ID.  Txn Id's start at
- * MAX_LOCKER_ID + 1 and go up to MAX_TXNID.
- */
-#define	MAX_LOCKER_ID	0x0fffffff
-#define	MAX_TXNID	0xffffffff
-
-/*
  * Out of band value for a lock.  The locks are returned to callers as offsets
  * into the lock regions.  Since the RLAYOUT structure begins all regions, an
  * offset of 0 is guaranteed not to be a valid lock.
diff --git a/db2/hash/hash.c b/db2/hash/hash.c
index 6d8c40057d..d986e08087 100644
--- a/db2/hash/hash.c
+++ b/db2/hash/hash.c
@@ -47,7 +47,7 @@
 #include "config.h"
 
 #ifndef lint
-static const char sccsid[] = "@(#)hash.c	10.25 (Sleepycat) 8/24/97";
+static const char sccsid[] = "@(#)hash.c	10.27 (Sleepycat) 9/15/97";
 #endif /* not lint */
 
 #ifndef NO_SYSTEM_INCLUDES
@@ -573,8 +573,6 @@ __ham_c_close(cursor)
 	DBC *cursor;
 {
 	DB  *ldbp;
-	HTAB *hashp;
-	HASH_CURSOR *hcp;
 	int ret;
 
 	DEBUG_LWRITE(cursor->dbp, cursor->txn, "ham_c_close", NULL, NULL, 0);
@@ -590,8 +588,32 @@ __ham_c_close(cursor)
 	if (F_ISSET(cursor->dbp, DB_AM_THREAD) &&
 	    (ret = __db_gethandle(cursor->dbp, __ham_hdup, &ldbp)) != 0)
 		return (ret);
-	hashp = (HTAB *)ldbp->internal;
-	hcp = (HASH_CURSOR *)cursor->internal;
+
+	ret = __ham_c_iclose(ldbp, cursor);
+
+	if (F_ISSET(ldbp, DB_AM_THREAD))
+		__db_puthandle(ldbp);
+	return (ret);
+}
+/*
+ * __ham_c_iclose --
+ *
+ * Internal cursor close routine; assumes it is being passed the correct
+ * handle, rather than getting and putting a handle.
+ *
+ * PUBLIC: int __ham_c_iclose __P((DB *, DBC *));
+ */
+int
+__ham_c_iclose(dbp, dbc)
+	DB *dbp;
+	DBC *dbc;
+{
+	HASH_CURSOR *hcp;
+	HTAB *hashp;
+	int ret;
+
+	hashp = (HTAB *)dbp->internal;
+	hcp = (HASH_CURSOR *)dbc->internal;
 	ret = __ham_item_done(hashp, hcp, 0);
 
 	if (hcp->big_key)
@@ -602,19 +624,16 @@ __ham_c_close(cursor)
 	/*
 	 * All cursors (except the default ones) are linked off the master.
 	 * Therefore, when we close the cursor, we have to remove it from
-	 * the master, not the local one.  When we are closing the file in
-	 * its entirety, then we clear the THREAD bit and the master and
-	 * local are identical, so we remove the correct one.
+	 * the master, not the local one.
+	 * XXX I am always removing from the master; what about local cursors?
 	 */
-	DB_THREAD_LOCK(cursor->dbp);
-	TAILQ_REMOVE(&cursor->dbp->curs_queue, cursor, links);
-	DB_THREAD_UNLOCK(cursor->dbp);
-
-	if (F_ISSET(cursor->dbp, DB_AM_THREAD))
-		__db_puthandle(ldbp);
+	DB_THREAD_LOCK(dbc->dbp);
+	TAILQ_REMOVE(&dbc->dbp->curs_queue, dbc, links);
+	DB_THREAD_UNLOCK(dbc->dbp);
 
 	FREE(hcp, sizeof(HASH_CURSOR));
-	FREE(cursor, sizeof(DBC));
+	FREE(dbc, sizeof(DBC));
+
 	return (ret);
 }
 
@@ -695,10 +714,9 @@ __ham_c_del(cursor, flags)
 			hcp->dndx = 0;				/* Case 2 */
 			hcp->dpgno = PGNO(hcp->dpagep);
 			if (ppgno == PGNO_INVALID)
-				memcpy(P_ENTRY(hcp->pagep,
-				    H_DATAINDEX(hcp->bndx)) +
-				    SSZ(HOFFDUP, pgno), &hcp->dpgno,
-				    sizeof(db_pgno_t));
+				memcpy(HOFFDUP_PGNO(P_ENTRY(hcp->pagep,
+				    H_DATAINDEX(hcp->bndx))),
+				    &hcp->dpgno, sizeof(db_pgno_t));
 			F_SET(hcp, H_DELETED);
 		} else					/* Case 1 */
 			F_SET(hcp, H_DELETED);
@@ -1051,18 +1069,17 @@ __ham_dup_return(hashp, hcp, val, flags)
 	DBT *val;
 	int flags;
 {
-	HKEYDATA *hk;
 	PAGE *pp;
 	DBT *myval, tmp_val;
 	db_indx_t ndx;
 	db_pgno_t pgno;
-	u_int8_t type;
+	u_int8_t *hk, type;
 	int indx, ret;
 	db_indx_t len;
 
 	/* Check for duplicate and return the first one. */
 	ndx = H_DATAINDEX(hcp->bndx);
-	type = GET_HKEYDATA(hcp->pagep, ndx)->type;
+	type = HPAGE_TYPE(hcp->pagep, ndx);
 	pp = hcp->pagep;
 	myval = val;
 
@@ -1088,7 +1105,8 @@ __ham_dup_return(hashp, hcp, val, flags)
 				hcp->dndx = 0;
 				hcp->dup_off = 0;
 				do {
-					memcpy(&len, hk->data + hcp->dup_off,
+					memcpy(&len,
+					    HKEYDATA_DATA(hk) + hcp->dup_off,
 					    sizeof(db_indx_t));
 					hcp->dup_off += DUP_SIZE(len);
 					hcp->dndx++;
@@ -1096,15 +1114,15 @@ __ham_dup_return(hashp, hcp, val, flags)
 				hcp->dup_off -= DUP_SIZE(len);
 				hcp->dndx--;
 			} else {
-				memcpy(&len, hk->data, sizeof(db_indx_t));
+				memcpy(&len,
+				    HKEYDATA_DATA(hk), sizeof(db_indx_t));
 				hcp->dup_off = 0;
 				hcp->dndx = 0;
 			}
 			hcp->dup_len = len;
 		} else if (type == H_OFFDUP) {
 			F_SET(hcp, H_ISDUP);
-			memcpy(&pgno,
-			    P_ENTRY(hcp->pagep, ndx) + SSZ(HOFFDUP, pgno),
+			memcpy(&pgno, HOFFDUP_PGNO(P_ENTRY(hcp->pagep, ndx)),
 			    sizeof(db_pgno_t));
 			if (flags == DB_LAST || flags == DB_PREV) {
 				indx = (int)hcp->dndx;
@@ -1166,7 +1184,7 @@ __ham_overwrite(hashp, hcp, nval)
 	DBT *nval;
 {
 	DBT *myval, tmp_val;
-	HKEYDATA *hk;
+	u_int8_t *hk;
 
 	if (F_ISSET(hashp->dbp, DB_AM_DUP))
 		return (__ham_add_dup(hashp, hcp, nval, DB_KEYLAST));
@@ -1176,10 +1194,9 @@ __ham_overwrite(hashp, hcp, nval)
 		F_SET(&tmp_val, DB_DBT_PARTIAL);
 		tmp_val.doff = 0;
 		hk = H_PAIRDATA(hcp->pagep, hcp->bndx);
-		if (hk->type == H_OFFPAGE)
+		if (HPAGE_PTYPE(hk) == H_OFFPAGE)
 			memcpy(&tmp_val.dlen,
-			    (u_int8_t *)hk + SSZ(HOFFPAGE, tlen),
-			    sizeof(u_int32_t));
+			    HOFFPAGE_TLEN(hk), sizeof(u_int32_t));
 		else
 			tmp_val.dlen = LEN_HDATA(hcp->pagep,
 			    hashp->hdr->pagesize,hcp->bndx);
@@ -1207,10 +1224,10 @@ __ham_lookup(hashp, hcp, key, sought, mode)
 	u_int32_t sought;
 	db_lockmode_t mode;
 {
-	HKEYDATA *hk;
 	db_pgno_t pgno;
 	u_int32_t tlen;
 	int match, ret, t_ret;
+	u_int8_t *hk;
 
 	/*
 	 * Set up cursor so that we're looking for space to add an item
@@ -1229,14 +1246,12 @@ __ham_lookup(hashp, hcp, key, sought, mode)
 			break;
 
 		hk = H_PAIRKEY(hcp->pagep, hcp->bndx);
-		switch (hk->type) {
+		switch (HPAGE_PTYPE(hk)) {
 		case H_OFFPAGE:
-			memcpy(&tlen, (u_int8_t *)hk + SSZ(HOFFPAGE, tlen),
-			    sizeof(u_int32_t));
+			memcpy(&tlen, HOFFPAGE_TLEN(hk), sizeof(u_int32_t));
 			if (tlen == key->size) {
 				memcpy(&pgno,
-				    (u_int8_t *)hk + SSZ(HOFFPAGE, pgno),
-				    sizeof(db_pgno_t));
+				    HOFFPAGE_PGNO(hk), sizeof(db_pgno_t));
 				match = __db_moff(hashp->dbp, key, pgno);
 				if (match == 0) {
 					F_SET(hcp, H_OK);
@@ -1247,7 +1262,8 @@ __ham_lookup(hashp, hcp, key, sought, mode)
 		case H_KEYDATA:
 			if (key->size == LEN_HKEY(hcp->pagep,
 			    hashp->hdr->pagesize, hcp->bndx) &&
-			    memcmp(key->data, hk->data, key->size) == 0) {
+			    memcmp(key->data,
+			    HKEYDATA_DATA(hk), key->size) == 0) {
 				F_SET(hcp, H_OK);
 				return (0);
 			}
diff --git a/db2/hash/hash_auto.c b/db2/hash/hash_auto.c
index f8ab80c8ee..2279de9668 100644
--- a/db2/hash/hash_auto.c
+++ b/db2/hash/hash_auto.c
@@ -138,7 +138,7 @@ __ham_insdel_print(notused1, dbtp, lsnp, notused3, notused4)
 	notused3 = 0;
 	notused4 = NULL;
 
-	if((ret = __ham_insdel_read(dbtp->data, &argp)) != 0)
+	if ((ret = __ham_insdel_read(dbtp->data, &argp)) != 0)
 		return (ret);
 	printf("[%lu][%lu]ham_insdel: rec: %lu txnid %lx prevlsn [%lu][%lu]\n",
 	    (u_long)lsnp->file,
@@ -335,7 +335,7 @@ __ham_newpage_print(notused1, dbtp, lsnp, notused3, notused4)
 	notused3 = 0;
 	notused4 = NULL;
 
-	if((ret = __ham_newpage_read(dbtp->data, &argp)) != 0)
+	if ((ret = __ham_newpage_read(dbtp->data, &argp)) != 0)
 		return (ret);
 	printf("[%lu][%lu]ham_newpage: rec: %lu txnid %lx prevlsn [%lu][%lu]\n",
 	    (u_long)lsnp->file,
@@ -498,7 +498,7 @@ __ham_splitmeta_print(notused1, dbtp, lsnp, notused3, notused4)
 	notused3 = 0;
 	notused4 = NULL;
 
-	if((ret = __ham_splitmeta_read(dbtp->data, &argp)) != 0)
+	if ((ret = __ham_splitmeta_read(dbtp->data, &argp)) != 0)
 		return (ret);
 	printf("[%lu][%lu]ham_splitmeta: rec: %lu txnid %lx prevlsn [%lu][%lu]\n",
 	    (u_long)lsnp->file,
@@ -659,7 +659,7 @@ __ham_splitdata_print(notused1, dbtp, lsnp, notused3, notused4)
 	notused3 = 0;
 	notused4 = NULL;
 
-	if((ret = __ham_splitdata_read(dbtp->data, &argp)) != 0)
+	if ((ret = __ham_splitdata_read(dbtp->data, &argp)) != 0)
 		return (ret);
 	printf("[%lu][%lu]ham_splitdata: rec: %lu txnid %lx prevlsn [%lu][%lu]\n",
 	    (u_long)lsnp->file,
@@ -851,7 +851,7 @@ __ham_replace_print(notused1, dbtp, lsnp, notused3, notused4)
 	notused3 = 0;
 	notused4 = NULL;
 
-	if((ret = __ham_replace_read(dbtp->data, &argp)) != 0)
+	if ((ret = __ham_replace_read(dbtp->data, &argp)) != 0)
 		return (ret);
 	printf("[%lu][%lu]ham_replace: rec: %lu txnid %lx prevlsn [%lu][%lu]\n",
 	    (u_long)lsnp->file,
@@ -1053,7 +1053,7 @@ __ham_newpgno_print(notused1, dbtp, lsnp, notused3, notused4)
 	notused3 = 0;
 	notused4 = NULL;
 
-	if((ret = __ham_newpgno_read(dbtp->data, &argp)) != 0)
+	if ((ret = __ham_newpgno_read(dbtp->data, &argp)) != 0)
 		return (ret);
 	printf("[%lu][%lu]ham_newpgno: rec: %lu txnid %lx prevlsn [%lu][%lu]\n",
 	    (u_long)lsnp->file,
@@ -1218,7 +1218,7 @@ __ham_ovfl_print(notused1, dbtp, lsnp, notused3, notused4)
 	notused3 = 0;
 	notused4 = NULL;
 
-	if((ret = __ham_ovfl_read(dbtp->data, &argp)) != 0)
+	if ((ret = __ham_ovfl_read(dbtp->data, &argp)) != 0)
 		return (ret);
 	printf("[%lu][%lu]ham_ovfl: rec: %lu txnid %lx prevlsn [%lu][%lu]\n",
 	    (u_long)lsnp->file,
diff --git a/db2/hash/hash_conv.c b/db2/hash/hash_conv.c
index 22901af950..9cebe72390 100644
--- a/db2/hash/hash_conv.c
+++ b/db2/hash/hash_conv.c
@@ -7,7 +7,7 @@
 #include "config.h"
 
 #ifndef lint
-static const char sccsid[] = "@(#)hash_conv.c	10.3 (Sleepycat) 6/21/97";
+static const char sccsid[] = "@(#)hash_conv.c	10.4 (Sleepycat) 9/15/97";
 #endif /* not lint */
 
 #ifndef NO_SYSTEM_INCLUDES
@@ -20,12 +20,11 @@ static const char sccsid[] = "@(#)hash_conv.c	10.3 (Sleepycat) 6/21/97";
 #include "hash.h"
 
 /*
- * __h_pgin, __ham_pgout --
- *	Convert host-specific page layout to/from the host-independent
- *	format stored on disk.
+ * __ham_pgin --
+ *	Convert host-specific page layout from the host-independent format
+ *	stored on disk.
  *
  * PUBLIC: int __ham_pgin __P((db_pgno_t, void *, DBT *));
- * PUBLIC: int __ham_pgout __P((db_pgno_t, void *, DBT *));
  */
 int
 __ham_pgin(pg, pp, cookie)
@@ -49,9 +48,17 @@ __ham_pgin(pg, pp, cookie)
 
 	if (!pginfo->needswap)
 		return (0);
-	return (pg == PGNO_METADATA ? __ham_mswap(pp) : __db_pgin(pg, pp));
+	return (pg == PGNO_METADATA ?
+	    __ham_mswap(pp) : __db_pgin(pg, pginfo->db_pagesize, pp));
 }
 
+/*
+ * __ham_pgout --
+ *	Convert host-specific page layout to the host-independent format
+ *	stored on disk.
+ *
+ * PUBLIC: int __ham_pgout __P((db_pgno_t, void *, DBT *));
+ */
 int
 __ham_pgout(pg, pp, cookie)
 	db_pgno_t pg;
@@ -63,7 +70,8 @@ __ham_pgout(pg, pp, cookie)
 	pginfo = (DB_PGINFO *)cookie->data;
 	if (!pginfo->needswap)
 		return (0);
-	return (pg == PGNO_METADATA ? __ham_mswap(pp) : __db_pgout(pg, pp));
+	return (pg == PGNO_METADATA ?
+	    __ham_mswap(pp) : __db_pgout(pg, pginfo->db_pagesize, pp));
 }
 
 /*
diff --git a/db2/hash/hash_dup.c b/db2/hash/hash_dup.c
index c9590fa49d..71bd1c5eb0 100644
--- a/db2/hash/hash_dup.c
+++ b/db2/hash/hash_dup.c
@@ -42,7 +42,7 @@
 #include "config.h"
 
 #ifndef lint
-static const char sccsid[] = "@(#)hash_dup.c	10.6 (Sleepycat) 9/3/97";
+static const char sccsid[] = "@(#)hash_dup.c	10.7 (Sleepycat) 9/15/97";
 #endif /* not lint */
 
 /*
@@ -99,9 +99,9 @@ __ham_add_dup(hashp, hcp, nval, flags)
 	int flags;
 {
 	DBT pval, tmp_val;
-	HKEYDATA *hk;
 	u_int32_t del_len, new_size;
 	int ret;
+	u_int8_t *hk;
 
 	if (flags == DB_CURRENT && hcp->dpgno == PGNO_INVALID)
 		del_len = hcp->dup_len;
@@ -128,8 +128,8 @@ __ham_add_dup(hashp, hcp, nval, flags)
 	 * the addition of the new item will make the set large, or
 	 * if there isn't enough room on this page to add the next item.
 	 */
-	if (hk->type != H_OFFDUP &&
-	    (hk->type == H_OFFPAGE || ISBIG(hashp, new_size) ||
+	if (HPAGE_PTYPE(hk) != H_OFFDUP &&
+	    (HPAGE_PTYPE(hk) == H_OFFPAGE || ISBIG(hashp, new_size) ||
 	    DUP_SIZE(nval->size) - del_len > P_FREESPACE(hcp->pagep))) {
 
 		if ((ret = __ham_dup_convert(hashp, hcp)) != 0)
@@ -139,16 +139,17 @@ __ham_add_dup(hashp, hcp, nval, flags)
 	}
 
 	/* There are two separate cases here: on page and off page. */
-	if (hk->type != H_OFFDUP) {
-		if (hk->type != H_DUPLICATE) {
-			hk->type = H_DUPLICATE;
+	if (HPAGE_PTYPE(hk) != H_OFFDUP) {
+		if (HPAGE_PTYPE(hk) != H_DUPLICATE) {
+			HPAGE_PTYPE(hk) = H_DUPLICATE;
 			pval.flags = 0;
-			pval.data = hk->data;
+			pval.data = HKEYDATA_DATA(hk);
 			pval.size = LEN_HDATA(hcp->pagep, hashp->hdr->pagesize,
 			    hcp->bndx);
-			if ((ret = __ham_make_dup(&pval, &tmp_val, &hcp->big_data,
-			    &hcp->big_datalen)) != 0 ||
-			    (ret = __ham_replpair(hashp, hcp, &tmp_val, 1)) != 0)
+			if ((ret =
+			    __ham_make_dup(&pval, &tmp_val, &hcp->big_data,
+			    &hcp->big_datalen)) != 0 || (ret =
+			    __ham_replpair(hashp, hcp, &tmp_val, 1)) != 0)
 				return (ret);
 		}
 
@@ -187,8 +188,7 @@ __ham_add_dup(hashp, hcp, nval, flags)
 
 	/* If we get here, then we're on duplicate pages. */
 	if (hcp->dpgno == PGNO_INVALID) {
-		memcpy(&hcp->dpgno,
-		    (u_int8_t *)hk + SSZ(HOFFDUP, pgno), sizeof(db_pgno_t));
+		memcpy(&hcp->dpgno, HOFFDUP_PGNO(hk), sizeof(db_pgno_t));
 		hcp->dndx = 0;
 	}
 
@@ -259,14 +259,13 @@ __ham_dup_convert(hashp, hcp)
 	 * Now put the duplicates onto the new page.
 	 */
 	dbt.flags = 0;
-	switch (((HKEYDATA *)H_PAIRDATA(hcp->pagep, hcp->bndx))->type) {
+	switch (HPAGE_PTYPE(H_PAIRDATA(hcp->pagep, hcp->bndx))) {
 	case H_KEYDATA:
 		/* Simple case, one key on page; move it to dup page. */
 		dndx = 0;
 		dbt.size =
 		    LEN_HDATA(hcp->pagep, hashp->hdr->pagesize, hcp->bndx);
-		dbt.data =
-		    ((HKEYDATA *)H_PAIRDATA(hcp->pagep, hcp->bndx))->data;
+		dbt.data = HKEYDATA_DATA(H_PAIRDATA(hcp->pagep, hcp->bndx));
 		ret = __db_pitem(hashp->dbp, hcp->dpagep,
 		    (u_int32_t)dndx, BKEYDATA_SIZE(dbt.size), NULL, &dbt);
 		if (ret == 0)
@@ -289,7 +288,7 @@ __ham_dup_convert(hashp, hcp)
 			__ham_dirty_page(hashp, hcp->dpagep);
 		break;
 	case H_DUPLICATE:
-		p = ((HKEYDATA *)H_PAIRDATA(hcp->pagep, hcp->bndx))->data;
+		p = HKEYDATA_DATA(H_PAIRDATA(hcp->pagep, hcp->bndx));
 		pend = p +
 		    LEN_HDATA(hcp->pagep, hashp->hdr->pagesize, hcp->bndx);
 
@@ -366,24 +365,23 @@ __ham_check_move(hashp, hcp, add_len)
 {
 	DBT k, d;
 	DB_LSN new_lsn;
-	HKEYDATA *hk;
 	PAGE *next_pagep;
 	db_pgno_t next_pgno;
 	int rectype, ret;
 	u_int32_t new_datalen, old_len;
+	u_int8_t *hk;
 
 	/*
 	 * Check if we can do whatever we need to on this page.  If not,
 	 * then we'll have to move the current element to a new page.
 	 */
-
 	hk = H_PAIRDATA(hcp->pagep, hcp->bndx);
 
 	/*
 	 * If the item is already off page duplicates or an offpage item,
 	 * then we know we can do whatever we need to do in-place
 	 */
-	if (hk->type == H_OFFDUP || hk->type == H_OFFPAGE)
+	if (HPAGE_PTYPE(hk) == H_OFFDUP || HPAGE_PTYPE(hk) == H_OFFPAGE)
 		return (0);
 
 	old_len =
@@ -443,22 +441,25 @@ __ham_check_move(hashp, hcp, add_len)
 		rectype = PUTPAIR;
 		k.flags = 0;
 		d.flags = 0;
-		if (H_PAIRKEY(hcp->pagep, hcp->bndx)->type == H_OFFPAGE) {
+		if (HPAGE_PTYPE(
+		    H_PAIRKEY(hcp->pagep, hcp->bndx)) == H_OFFPAGE) {
 			rectype |= PAIR_KEYMASK;
 			k.data = H_PAIRKEY(hcp->pagep, hcp->bndx);
 			k.size = HOFFPAGE_SIZE;
 		} else {
-			k.data = H_PAIRKEY(hcp->pagep, hcp->bndx)->data;
+			k.data =
+			    HKEYDATA_DATA(H_PAIRKEY(hcp->pagep, hcp->bndx));
 			k.size = LEN_HKEY(hcp->pagep,
 			    hashp->hdr->pagesize, hcp->bndx);
 		}
 
-		if (hk->type == H_OFFPAGE) {
+		if (HPAGE_PTYPE(hk) == H_OFFPAGE) {
 			rectype |= PAIR_DATAMASK;
 			d.data = H_PAIRDATA(hcp->pagep, hcp->bndx);
 			d.size = HOFFPAGE_SIZE;
 		} else {
-			d.data = H_PAIRDATA(hcp->pagep, hcp->bndx)->data;
+			d.data =
+			    HKEYDATA_DATA(H_PAIRDATA(hcp->pagep, hcp->bndx));
 			d.size = LEN_HDATA(hcp->pagep,
 			    hashp->hdr->pagesize, hcp->bndx);
 		}
diff --git a/db2/hash/hash_func.c b/db2/hash/hash_func.c
index 2ef47afb57..1bf12c4948 100644
--- a/db2/hash/hash_func.c
+++ b/db2/hash/hash_func.c
@@ -47,7 +47,7 @@
 #include "config.h"
 
 #ifndef lint
-static const char sccsid[] = "@(#)hash_func.c	10.6 (Sleepycat) 7/26/97";
+static const char sccsid[] = "@(#)hash_func.c	10.7 (Sleepycat) 9/16/97";
 #endif /* not lint */
 
 #ifndef NO_SYSTEM_INCLUDES
@@ -64,7 +64,7 @@ static const char sccsid[] = "@(#)hash_func.c	10.6 (Sleepycat) 7/26/97";
  *
  * PUBLIC: u_int32_t __ham_func2 __P((const void *, u_int32_t));
  */
-#define	dcharhash(h, c)	((h) = 0x63c63cd9*(h) + 0x9c39c33d + (c))
+#define	DCHARHASH(h, c)	((h) = 0x63c63cd9*(h) + 0x9c39c33d + (c))
 
 u_int32_t
 __ham_func2(key, len)
@@ -81,7 +81,7 @@ __ham_func2(key, len)
 		c = *k++;
 		if (!c && k > e)
 			break;
-		dcharhash(h, c);
+		DCHARHASH(h, c);
 	}
 	return (h);
 }
diff --git a/db2/hash/hash_page.c b/db2/hash/hash_page.c
index 68c31b14f9..8ba42da1a4 100644
--- a/db2/hash/hash_page.c
+++ b/db2/hash/hash_page.c
@@ -47,10 +47,9 @@
 #include "config.h"
 
 #ifndef lint
-static const char sccsid[] = "@(#)hash_page.c	10.18 (Sleepycat) 8/21/97";
+static const char sccsid[] = "@(#)hash_page.c	10.24 (Sleepycat) 9/17/97";
 #endif /* not lint */
 
-
 /*
  * PACKAGE:  hashing
  *
@@ -85,7 +84,7 @@ static const char sccsid[] = "@(#)hash_page.c	10.18 (Sleepycat) 8/21/97";
 static int __ham_lock_bucket __P((DB *, HASH_CURSOR *, db_lockmode_t));
 
 #ifdef DEBUG_SLOW
-static void	 account_page(HTAB *, db_pgno_t, int);
+static void  __account_page(HTAB *, db_pgno_t, int);
 #endif
 
 /*
@@ -121,7 +120,7 @@ __ham_item(hashp, cursorp, mode)
 		 * pointer to be the beginning of the datum.
 		 */
 		memcpy(&cursorp->dup_len,
-		    H_PAIRDATA(cursorp->pagep, cursorp->bndx)->data +
+		    HKEYDATA_DATA(H_PAIRDATA(cursorp->pagep, cursorp->bndx)) +
 		    cursorp->dup_off, sizeof(db_indx_t));
 	else if (F_ISSET(cursorp, H_ISDUP)) {
 		/* Make sure we're not about to run off the page. */
@@ -326,8 +325,8 @@ __ham_item_prev(hashp, cursorp, mode)
 				else {
 					HASH_CURSOR *h;
 					h = cursorp;
-					memcpy(&h->dup_len,
-					    H_PAIRDATA(h->pagep, h->bndx)->data
+					memcpy(&h->dup_len, HKEYDATA_DATA(
+					    H_PAIRDATA(h->pagep, h->bndx))
 					    + h->dup_off - sizeof(db_indx_t),
 					    sizeof(db_indx_t));
 					cursorp->dup_off -=
@@ -481,7 +480,7 @@ __ham_putitem(p, dbt, type)
 	} else {
 		off = HOFFSET(p) - HKEYDATA_SIZE(dbt->size);
 		HOFFSET(p) = p->inp[n] = off;
-		PUT_HKEYDATA(GET_HKEYDATA(p, n), dbt->data, dbt->size, type);
+		PUT_HKEYDATA(P_ENTRY(p, n), dbt->data, dbt->size, type);
 	}
 
 	/* Adjust page info. */
@@ -524,24 +523,24 @@ __ham_del_pair(hashp, cursorp)
 	 * entry referring to the big item.
 	 */
 	ret = 0;
-	if (H_PAIRKEY(p, ndx)->type == H_OFFPAGE) {
-		memcpy(&pgno, (u_int8_t *)GET_HOFFPAGE(p, H_KEYINDEX(ndx)) +
-		    SSZ(HOFFPAGE, pgno), sizeof(db_pgno_t));
+	if (HPAGE_PTYPE(H_PAIRKEY(p, ndx)) == H_OFFPAGE) {
+		memcpy(&pgno, HOFFPAGE_PGNO(P_ENTRY(p, H_KEYINDEX(ndx))),
+		    sizeof(db_pgno_t));
 		ret = __db_doff(hashp->dbp, pgno, __ham_del_page);
 	}
 
 	if (ret == 0)
-		switch (H_PAIRDATA(p, ndx)->type) {
+		switch (HPAGE_PTYPE(H_PAIRDATA(p, ndx))) {
 		case H_OFFPAGE:
 			memcpy(&pgno,
-			    (u_int8_t *)GET_HOFFPAGE(p, H_DATAINDEX(ndx)) +
-			    SSZ(HOFFPAGE, pgno), sizeof(db_pgno_t));
+			    HOFFPAGE_PGNO(P_ENTRY(p, H_DATAINDEX(ndx))),
+			    sizeof(db_pgno_t));
 			ret = __db_doff(hashp->dbp, pgno, __ham_del_page);
 			break;
 		case H_OFFDUP:
 			memcpy(&pgno,
-			    (u_int8_t *)GET_HOFFDUP(p, H_DATAINDEX(ndx)) +
-			    SSZ(HOFFDUP, pgno), sizeof(db_pgno_t));
+			    HOFFDUP_PGNO(P_ENTRY(p, H_DATAINDEX(ndx))),
+			    sizeof(db_pgno_t));
 			ret = __db_ddup(hashp->dbp, pgno, __ham_del_page);
 			break;
 		}
@@ -706,13 +705,12 @@ __ham_replpair(hashp, hcp, dbt, make_dup)
 	DBT *dbt;
 	u_int32_t make_dup;
 {
-	DBT old_dbt, tmp;
+	DBT old_dbt, tdata, tmp;
 	DB_LSN	new_lsn;
-	HKEYDATA *hk;
 	u_int32_t len;
 	int32_t change;
 	int is_big, ret, type;
-	u_int8_t *beg, *dest, *end, *src;
+	u_int8_t *beg, *dest, *end, *hk, *src;
 
 	/*
 	 * Big item replacements are handled in generic code.
@@ -738,11 +736,10 @@ __ham_replpair(hashp, hcp, dbt, make_dup)
 	change = dbt->size - dbt->dlen;
 
 	hk = H_PAIRDATA(hcp->pagep, hcp->bndx);
-	is_big = hk->type == H_OFFPAGE;
+	is_big = HPAGE_PTYPE(hk) == H_OFFPAGE;
 
 	if (is_big)
-		memcpy(&len, (u_int8_t *)hk + SSZ(HOFFPAGE, tlen),
-		    sizeof(u_int32_t));
+		memcpy(&len, HOFFPAGE_TLEN(hk), sizeof(u_int32_t));
 	else
 		len = LEN_HKEYDATA(hcp->pagep,
 		    hashp->dbp->pgsize, H_DATAINDEX(hcp->bndx));
@@ -770,13 +767,14 @@ __ham_replpair(hashp, hcp, dbt, make_dup)
 		    &tmp, &hcp->big_key, &hcp->big_keylen)) != 0)
 			return (ret);
 
-		type = hk->type;
 		if (dbt->doff == 0 && dbt->dlen == len) {
 			ret = __ham_del_pair(hashp, hcp);
 			if (ret == 0)
-			    ret = __ham_add_el(hashp, hcp, &tmp, dbt, type);
+			    ret = __ham_add_el(hashp,
+			        hcp, &tmp, dbt, H_KEYDATA);
 		} else {					/* Case B */
-			DBT tdata;
+			type = HPAGE_PTYPE(hk) != H_OFFPAGE ?
+			    HPAGE_PTYPE(hk) : H_KEYDATA;
 			tdata.flags = 0;
 			F_SET(&tdata, DB_DBT_MALLOC | DB_DBT_INTERNAL);
 
@@ -824,7 +822,7 @@ err:		free(tmp.data);
 	 * Set up pointer into existing data. Do it before the log
 	 * message so we can use it inside of the log setup.
 	 */
-	beg = H_PAIRDATA(hcp->pagep, hcp->bndx)->data;
+	beg = HKEYDATA_DATA(H_PAIRDATA(hcp->pagep, hcp->bndx));
 	beg += dbt->doff;
 
 	/*
@@ -885,11 +883,11 @@ __ham_onpage_replace(pagep, pgsize, ndx, off, change, dbt)
 		if (off < 0)
 			len = pagep->inp[ndx] - HOFFSET(pagep);
 		else if ((u_int32_t)off >= LEN_HKEYDATA(pagep, pgsize, ndx)) {
-			len = GET_HKEYDATA(pagep, ndx)->data +
+			len = HKEYDATA_DATA(P_ENTRY(pagep, ndx)) +
 			    LEN_HKEYDATA(pagep, pgsize, ndx) - src;
 			zero_me = 1;
 		} else
-			len = (GET_HKEYDATA(pagep, ndx)->data + off) - src;
+			len = (HKEYDATA_DATA(P_ENTRY(pagep, ndx)) + off) - src;
 		dest = src - change;
 		memmove(dest, src, len);
 		if (zero_me)
@@ -901,7 +899,7 @@ __ham_onpage_replace(pagep, pgsize, ndx, off, change, dbt)
 		HOFFSET(pagep) -= change;
 	}
 	if (off >= 0)
-		memcpy(GET_HKEYDATA(pagep, ndx)->data + off,
+		memcpy(HKEYDATA_DATA(P_ENTRY(pagep, ndx)) + off,
 		    dbt->data, dbt->size);
 	else
 		memcpy(P_ENTRY(pagep, ndx), dbt->data, dbt->size);
@@ -1319,7 +1317,7 @@ __ham_new_page(hashp, addr, type, pp)
 		return (ret);
 
 #ifdef DEBUG_SLOW
-	account_page(hashp, addr, 1);
+	__account_page(hashp, addr, 1);
 #endif
 	/* This should not be necessary because page-in should do it. */
 	P_INIT(pagep,
@@ -1398,7 +1396,7 @@ __ham_put_page(dbp, pagep, is_dirty)
 	int32_t is_dirty;
 {
 #ifdef DEBUG_SLOW
-	account_page((HTAB *)dbp->cookie,
+	__account_page((HTAB *)dbp->cookie,
 	    ((BKT *)((char *)pagep - sizeof(BKT)))->pgno, -1);
 #endif
 	return (memp_fput(dbp->mpf, pagep, (is_dirty ? DB_MPOOL_DIRTY : 0)));
@@ -1432,7 +1430,7 @@ __ham_get_page(dbp, addr, pagep)
 	ret = memp_fget(dbp->mpf, &addr, DB_MPOOL_CREATE, pagep);
 #ifdef DEBUG_SLOW
 	if (*pagep != NULL)
-		account_page((HTAB *)dbp->internal, addr, 1);
+		__account_page((HTAB *)dbp->internal, addr, 1);
 #endif
 	return (ret);
 }
@@ -1523,11 +1521,11 @@ __ham_overflow_page(dbp, type, pp)
 #ifdef DEBUG
 /*
  * PUBLIC: #ifdef DEBUG
- * PUBLIC: int bucket_to_page __P((HTAB *, int));
+ * PUBLIC: int __bucket_to_page __P((HTAB *, int));
  * PUBLIC: #endif
  */
 int
-bucket_to_page(hashp, n)
+__bucket_to_page(hashp, n)
 	HTAB *hashp;
 	int n;
 {
@@ -1735,7 +1733,7 @@ __ham_dpair(dbp, p, pndx)
 
 #ifdef DEBUG_SLOW
 static void
-account_page(hashp, pgno, inout)
+__account_page(hashp, pgno, inout)
 	HTAB *hashp;
 	db_pgno_t pgno;
 	int inout;
@@ -1767,7 +1765,8 @@ account_page(hashp, pgno, inout)
 		last--;
 	}
 	for (i = 0; i < last; i++, list[i].times++)
-		if (list[i].times > 20 && !is_bitmap_pgno(hashp, list[i].pgno))
+		if (list[i].times > 20 &&
+		    !__is_bitmap_pgno(hashp, list[i].pgno))
 			(void)fprintf(stderr,
 			    "Warning: pg %lu has been out for %d times\n",
 			    (u_long)list[i].pgno, list[i].times);
diff --git a/db2/hash/hash_rec.c b/db2/hash/hash_rec.c
index 81d9bb5ea8..1b30be337d 100644
--- a/db2/hash/hash_rec.c
+++ b/db2/hash/hash_rec.c
@@ -47,7 +47,7 @@
 #include "config.h"
 
 #ifndef lint
-static const char sccsid[] = "@(#)hash_rec.c	10.12 (Sleepycat) 8/22/97";
+static const char sccsid[] = "@(#)hash_rec.c	10.13 (Sleepycat) 9/15/97";
 #endif /* not lint */
 
 #ifndef NO_SYSTEM_INCLUDES
@@ -364,11 +364,11 @@ __ham_replace_recover(logp, dbtp, lsnp, redo, info)
 	DB *mdbp, *file_dbp;
 	DB_MPOOLFILE *mpf;
 	DBT dbt;
-	HKEYDATA *hk;
 	HTAB *hashp;
 	PAGE *pagep;
 	int32_t grow;
 	int change, cmp_n, cmp_p, getmeta, ret;
+	u_int8_t *hk;
 
 	getmeta = 0;
 	hashp = NULL;				/* XXX: shut the compiler up. */
@@ -421,11 +421,11 @@ __ham_replace_recover(logp, dbtp, lsnp, redo, info)
 		__ham_onpage_replace(pagep,
 		    file_dbp->pgsize, argp->ndx, argp->off, grow, &dbt);
 		if (argp->makedup) {
-			hk = GET_HKEYDATA(pagep, argp->ndx);
+			hk = P_ENTRY(pagep, argp->ndx);
 			if (redo)
-				hk->type = H_DUPLICATE;
+				HPAGE_PTYPE(hk) = H_DUPLICATE;
 			else
-				hk->type = H_KEYDATA;
+				HPAGE_PTYPE(hk) = H_KEYDATA;
 		}
 	}
 
@@ -738,7 +738,7 @@ __ham_ovfl_recover(logp, dbtp, lsnp, redo, info)
 	DBT *dbtp;
 	DB_LSN *lsnp;
 	int redo;
-	 void *info;
+	void *info;
 {
 	__ham_ovfl_args *argp;
 	DB *mdbp, *file_dbp;
diff --git a/db2/include/btree.h b/db2/include/btree.h
index 5cf4224ae6..878096b7b2 100644
--- a/db2/include/btree.h
+++ b/db2/include/btree.h
@@ -43,7 +43,7 @@
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- *	@(#)btree.h	10.16 (Sleepycat) 8/24/97
+ *	@(#)btree.h	10.17 (Sleepycat) 9/23/97
  */
 
 /* Forward structure declarations. */
@@ -181,6 +181,12 @@ struct __cursor {
 #define	C_DELETED	0x0001
 #define	C_REPLACE	0x0002
 #define	C_REPLACE_SETUP	0x0004
+
+	/*
+	 * Internal cursor held for DB->get; don't hold locks unless involved
+	 * in a TXN.
+	 */
+#define	C_INTERNAL	0x0008
 	u_int32_t	 flags;
 };
 
diff --git a/db2/include/btree_ext.h b/db2/include/btree_ext.h
index dab0f5be4e..9133c58c6b 100644
--- a/db2/include/btree_ext.h
+++ b/db2/include/btree_ext.h
@@ -8,6 +8,7 @@ int __bam_pgin __P((db_pgno_t, void *, DBT *));
 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_ovfl_chk __P((DB *, CURSOR *, u_int32_t, int));
 int __bam_ca_delete __P((DB *, db_pgno_t, u_int32_t, CURSOR *));
@@ -51,6 +52,7 @@ int __bam_cdel_recover
 int __ram_open __P((DB *, DBTYPE, DB_INFO *));
 int __ram_cursor __P((DB *, DB_TXN *, DBC **));
 int __ram_close __P((DB *));
+int __ram_c_iclose __P((DB *, DBC *));
 void __ram_ca __P((DB *, db_recno_t, ca_recno_arg));
 int __ram_getno __P((DB *, const DBT *, db_recno_t *, int));
 int __ram_snapshot __P((DB *));
diff --git a/db2/include/db.h.src b/db2/include/db.h.src
index f9b29fa2af..63d9603dba 100644
--- a/db2/include/db.h.src
+++ b/db2/include/db.h.src
@@ -4,7 +4,7 @@
  * Copyright (c) 1996, 1997
  *	Sleepycat Software.  All rights reserved.
  *
- *	@(#)db.h.src	10.67 (Sleepycat) 8/25/97
+ *	@(#)db.h.src	10.77 (Sleepycat) 9/24/97
  */
 
 #ifndef _DB_H_
@@ -67,8 +67,8 @@
 
 #define	DB_VERSION_MAJOR	2
 #define	DB_VERSION_MINOR	3
-#define	DB_VERSION_PATCH	4
-#define	DB_VERSION_STRING	"Sleepycat Software: DB 2.3.4: (8/20/97)"
+#define	DB_VERSION_PATCH	10
+#define	DB_VERSION_STRING	"Sleepycat Software: DB 2.3.10: (9/24/97)"
 
 typedef	u_int32_t	db_pgno_t;	/* Page number type. */
 typedef	u_int16_t	db_indx_t;	/* Page offset type. */
@@ -329,6 +329,7 @@ struct __db_info {
 #define	DB_NEEDSPLIT		( -9)	/* Page needs to be split. */
 #define	DB_REGISTERED		(-10)	/* Entry was previously registered. */
 #define	DB_SWAPBYTES		(-11)	/* Database needs byte swapping. */
+#define DB_TXN_CKP		(-12)	/* Encountered ckp record in log. */
 
 struct __db_ilock {			/* Internal DB access method lock. */
 	db_pgno_t	pgno;		/* Page being locked. */
@@ -338,7 +339,7 @@ struct __db_ilock {			/* Internal DB access method lock. */
 
 /* DB access method description structure. */
 struct __db {
-	void	*mutex;			/* Synchronization for free threading */
+	void	*mutexp;		/* Synchronization for free threading */
 	DBTYPE	 type;			/* DB access method. */
 	DB_ENV	*dbenv;			/* DB_ENV structure. */
 	DB_ENV	*mp_dbenv;		/* DB_ENV for local mpool creation. */
@@ -640,11 +641,11 @@ extern "C" {
 #endif
 int	memp_close __P((DB_MPOOL *));
 int	memp_fclose __P((DB_MPOOLFILE *));
-int	memp_fget __P((DB_MPOOLFILE *, db_pgno_t *, unsigned long, void *));
+int	memp_fget __P((DB_MPOOLFILE *, db_pgno_t *, int, 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 *, unsigned long));
-int	memp_fset __P((DB_MPOOLFILE *, void *, unsigned long));
+int	memp_fput __P((DB_MPOOLFILE *, void *, int));
+int	memp_fset __P((DB_MPOOLFILE *, void *, int));
 int	memp_fsync __P((DB_MPOOLFILE *));
 int	memp_open __P((const char *, int, int, DB_ENV *, DB_MPOOL **));
 int	memp_register __P((DB_MPOOL *, int,
@@ -697,7 +698,7 @@ 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 *, long, long));
+int	  txn_checkpoint __P((const DB_TXNMGR *, int, int));
 int	  txn_commit __P((DB_TXN *));
 int	  txn_close __P((DB_TXNMGR *));
 u_int32_t txn_id __P((DB_TXN *));
diff --git a/db2/include/db_185.h.src b/db2/include/db_185.h.src
index 52fb3a0da1..3fbca8bfda 100644
--- a/db2/include/db_185.h.src
+++ b/db2/include/db_185.h.src
@@ -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.3 (Sleepycat) 7/27/97
+ *	@(#)db_185.h.src	8.4 (Sleepycat) 9/16/97
  */
 
 #ifndef _DB_185_H_
@@ -72,6 +72,14 @@
 @u_int32_decl@
 #endif
 
+/*
+ * XXX
+ * SGI/IRIX already has a pgno_t.
+ */
+#ifdef	sgi
+#define	pgno_t	db_pgno_t
+#endif
+
 #define	MAX_PAGE_NUMBER	0xffffffff	/* >= # of pages in a file */
 typedef u_int32_t	pgno_t;
 #define	MAX_PAGE_OFFSET	65535		/* >= # of bytes in a page */
diff --git a/db2/include/db_cxx.h b/db2/include/db_cxx.h
index 506aed845c..611d967ef9 100644
--- a/db2/include/db_cxx.h
+++ b/db2/include/db_cxx.h
@@ -4,7 +4,7 @@
  * Copyright (c) 1997
  *	Sleepycat Software.  All rights reserved.
  *
- *	@(#)db_cxx.h	10.7 (Sleepycat) 8/22/97
+ *	@(#)db_cxx.h	10.8 (Sleepycat) 9/20/97
  */
 
 #ifndef _DB_CXX_H_
@@ -303,9 +303,9 @@ class _exported DbMpoolFile
 {
 public:
     int close();
-    int get(db_pgno_t *pgnoaddr, unsigned long flags, void *pagep);
-    int put(void *pgaddr, unsigned long flags);
-    int set(void *pgaddr, unsigned long flags);
+    int get(db_pgno_t *pgnoaddr, int flags, void *pagep);
+    int put(void *pgaddr, int flags);
+    int set(void *pgaddr, int flags);
     int sync();
 
     static int open(DbMpool *mp, const char *file,
@@ -391,7 +391,7 @@ class _exported DbTxnMgr
 friend DbEnv;
 public:
     int begin(DbTxn *pid, DbTxn **tid);
-    int checkpoint(long kbyte, long min) const;
+    int checkpoint(int kbyte, int min) const;
     int close();
     int stat(DB_TXN_STAT **statp, void *(*db_malloc)(size_t));
 
diff --git a/db2/include/db_ext.h b/db2/include/db_ext.h
index 1cccb47617..b18b10ff7f 100644
--- a/db2/include/db_ext.h
+++ b/db2/include/db_ext.h
@@ -57,8 +57,8 @@ int __db_noop_print
 int __db_noop_read __P((void *, __db_noop_args **));
 int __db_init_print __P((DB_ENV *));
 int __db_init_recover __P((DB_ENV *));
-int __db_pgin __P((db_pgno_t, void *));
-int __db_pgout __P((db_pgno_t, void *));
+int __db_pgin __P((db_pgno_t, size_t, void *));
+int __db_pgout __P((db_pgno_t, size_t, void *));
 int __db_dispatch __P((DB_LOG *, DBT *, DB_LSN *, int, void *));
 int __db_add_recovery __P((DB_ENV *,
    int (*)(DB_LOG *, DBT *, DB_LSN *, int, void *), u_int32_t));
diff --git a/db2/include/db_int.h.src b/db2/include/db_int.h.src
index b60e5002e5..ebadb35d36 100644
--- a/db2/include/db_int.h.src
+++ b/db2/include/db_int.h.src
@@ -4,7 +4,7 @@
  * Copyright (c) 1996, 1997
  *	Sleepycat Software.  All rights reserved.
  *
- *	@(#)db_int.h.src	10.28 (Sleepycat) 8/20/97
+ *	@(#)db_int.h.src	10.30 (Sleepycat) 9/23/97
  */
 
 #ifndef _DB_INTERNAL_H_
@@ -177,11 +177,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)->mutex,  -1,		\
+	    __db_mutex_lock((db_mutex_t *)(dbp)->mutexp,  -1,		\
 	        (dbp)->dbenv == NULL ? NULL : (dbp)->dbenv->db_yield) : 0)
 #define	DB_THREAD_UNLOCK(dbp)						\
 	(F_ISSET(dbp, DB_AM_THREAD) ?					\
-	    __db_mutex_unlock((db_mutex_t *)(dbp)->mutex,  -1) : 0)
+	    __db_mutex_unlock((db_mutex_t *)(dbp)->mutexp,  -1) : 0)
 
 /* Btree/recno local statistics structure. */
 struct __db_bt_lstat;	typedef struct __db_bt_lstat DB_BTREE_LSTAT;
@@ -306,14 +306,6 @@ typedef struct __dbpginfo {
  * Transactions and recovery.
  *******************************************************/
 /*
- * The locker id space is divided between the transaction manager and the lock
- * manager.  Lockid's start at 0 and go to MAX_LOCKER_ID.  Txn Id's start at
- * MAX_LOCKER_ID + 1 and go up to MAX_TXNID.
- */
-#define	MAX_LOCKER_ID	0x0fffffff
-#define	MAX_TXNID	0xffffffff
-
-/*
  * Out of band value for a lock.  The locks are returned to callers as offsets
  * into the lock regions.  Since the RLAYOUT structure begins all regions, an
  * offset of 0 is guaranteed not to be a valid lock.
diff --git a/db2/include/db_page.h b/db2/include/db_page.h
index cde7ff9f2e..30f6072fc3 100644
--- a/db2/include/db_page.h
+++ b/db2/include/db_page.h
@@ -4,7 +4,7 @@
  * Copyright (c) 1996, 1997
  *	Sleepycat Software.  All rights reserved.
  *
- *	@(#)db_page.h	10.11 (Sleepycat) 9/3/97
+ *	@(#)db_page.h	10.13 (Sleepycat) 9/24/97
  */
 
 #ifndef _DB_PAGE_H_
@@ -273,6 +273,17 @@ typedef struct _db_page {
 #define	H_OFFDUP	4	/* Overflow page of duplicates. */
 
 /*
+ * !!!
+ * Items on hash pages are (potentially) unaligned, so we can never cast the
+ * (page + offset) pointer to an HKEYDATA, HOFFPAGE or HOFFDUP structure, as
+ * we do with B+tree on-page structures.  Because we frequently want the type
+ * field, it requires no alignment, and it's in the same location in all three
+ * structures, there's a pair of macros.
+ */
+#define	HPAGE_PTYPE(p)		(*(u_int8_t *)p)
+#define	HPAGE_TYPE(pg, indx)	(*P_ENTRY(pg, indx))
+
+/*
  * The first and second types are H_KEYDATA and H_DUPLICATE, represented
  * by the HKEYDATA structure:
  *
@@ -294,10 +305,7 @@ typedef struct _hkeydata {
 	u_int8_t  type;		/*    00: Page type. */
 	u_int8_t  data[1];	/* Variable length key/data item. */
 } HKEYDATA;
-
-/* Get a HKEYDATA item for a specific index. */
-#define	GET_HKEYDATA(pg, indx)						\
-	((HKEYDATA *)P_ENTRY(pg, indx))
+#define	HKEYDATA_DATA(p)	(((u_int8_t *)p) + SSZA(HKEYDATA, data))
 
 /*
  * The length of any HKEYDATA item. Note that indx is an element index,
@@ -333,8 +341,8 @@ typedef struct _hkeydata {
 #define H_NUMPAIRS(pg)			(NUM_ENT(pg) / 2)
 #define	H_KEYINDEX(pindx)		(2 * (pindx))
 #define	H_DATAINDEX(pindx)		((2 * (pindx)) + 1)
-#define	H_PAIRKEY(pg, pindx)		GET_HKEYDATA(pg, H_KEYINDEX(pindx))
-#define	H_PAIRDATA(pg, pindx)		GET_HKEYDATA(pg, H_DATAINDEX(pindx))
+#define	H_PAIRKEY(pg, pindx)		P_ENTRY(pg, H_KEYINDEX(pindx))
+#define	H_PAIRDATA(pg, pindx)		P_ENTRY(pg, H_DATAINDEX(pindx))
 #define H_PAIRSIZE(pg, psize, pindx)					\
 	(LEN_HITEM(pg, psize, H_KEYINDEX(pindx)) +			\
 	LEN_HITEM(pg, psize, H_DATAINDEX(pindx)))
@@ -355,9 +363,8 @@ typedef struct _hoffpage {
 	u_int32_t tlen;		/* 08-11: Total length of item. */
 } HOFFPAGE;
 
-/* Get a HOFFPAGE item for a specific index. */
-#define	GET_HOFFPAGE(pg, indx)						\
-	((HOFFPAGE *)P_ENTRY(pg, indx))
+#define	HOFFPAGE_PGNO(p)	(((u_int8_t *)p) + SSZ(HOFFPAGE, pgno))
+#define	HOFFPAGE_TLEN(p)	(((u_int8_t *)p) + SSZ(HOFFPAGE, tlen))
 
 /*
  * Page space required to add a new HOFFPAGE item to the page, with and
@@ -378,10 +385,7 @@ typedef struct _hoffdup {
 	u_int8_t  unused[3];	/* 01-03: Padding, unused. */
 	db_pgno_t pgno;		/* 04-07: Offpage page number. */
 } HOFFDUP;
-
-/* Get a HOFFDUP item for a specific index. */
-#define	GET_HOFFDUP(pg, indx)						\
-	((HOFFDUP *)P_ENTRY(pg, indx))
+#define	HOFFDUP_PGNO(p)		(((u_int8_t *)p) + SSZ(HOFFDUP, pgno))
 
 /*
  * Page space required to add a new HOFFDUP item to the page, with and
diff --git a/db2/include/db_shash.h b/db2/include/db_shash.h
index f695a2bafa..b94e0f1d41 100644
--- a/db2/include/db_shash.h
+++ b/db2/include/db_shash.h
@@ -4,14 +4,14 @@
  * Copyright (c) 1996, 1997
  *	Sleepycat Software.  All rights reserved.
  *
- *	@(#)db_shash.h	10.1 (Sleepycat) 4/12/97
+ *	@(#)db_shash.h	10.2 (Sleepycat) 9/16/97
  */
 
 /* Hash Headers */
 typedef	SH_TAILQ_HEAD(hash_head) DB_HASHTAB;
 
 /*
- * __db_hashlookup --
+ * HASHLOOKUP --
  *
  * Look up something in a shared memory hash table.  The "elt" argument
  * should be a key, and cmp_func must know how to compare a key to whatever
@@ -30,7 +30,7 @@ typedef	SH_TAILQ_HEAD(hash_head) DB_HASHTAB;
  * If the element is not in the hash table, this macro exits with result
  * set to NULL.
  */
-#define	__db_hashlookup(begin, type, field, elt, r, n, hash, cmp) do {	\
+#define	HASHLOOKUP(begin, type, field, elt, r, n, hash, cmp) do {	\
 	DB_HASHTAB *__bucket;						\
 	u_int32_t __ndx;						\
 									\
@@ -43,10 +43,10 @@ typedef	SH_TAILQ_HEAD(hash_head) DB_HASHTAB;
 } while(0)
 
 /*
- * __db_hashinsert --
+ * HASHINSERT --
  *
  * Insert a new entry into the hash table.  This assumes that lookup has
- * failed; don't call it if you haven't already called __db_hashlookup.
+ * failed; don't call it if you haven't already called HASHLOOKUP.
  * begin: the beginning address of the hash table.
  * type: the structure type of the elements that are linked in each bucket.
  * field: the name of the field by which the "type" structures are linked.
@@ -54,7 +54,7 @@ typedef	SH_TAILQ_HEAD(hash_head) DB_HASHTAB;
  * nelems: the number of buckets in the hash table.
  * hash_func: the hash function that operates on elements of the type of elt
  */
-#define	__db_hashinsert(begin, type, field, elt, n, hash) do {		\
+#define	HASHINSERT(begin, type, field, elt, n, hash) do {		\
 	u_int32_t __ndx;						\
 	DB_HASHTAB *__bucket;						\
 									\
@@ -64,7 +64,7 @@ typedef	SH_TAILQ_HEAD(hash_head) DB_HASHTAB;
 } while(0)
 
 /*
- * __db_hashremove --
+ * HASHREMOVE --
  *	Remove the entry with a key == elt.
  * begin: address of the beginning of the hash table.
  * type: the structure type of the elements that are linked in each bucket.
@@ -75,19 +75,19 @@ typedef	SH_TAILQ_HEAD(hash_head) DB_HASHTAB;
  * cmp_func: compare elements of the type of elt with those in the table (of
  *	type "type").
  */
-#define	__db_hashremove(begin, type, field, elt, n, hash, cmp) {	\
+#define	HASHREMOVE(begin, type, field, elt, n, hash, cmp) {		\
 	u_int32_t __ndx;						\
 	DB_HASHTAB *__bucket;						\
 	SH_TAILQ_ENTRY *__entp;						\
 									\
 	__ndx = hash(elt) % (n);					\
 	__bucket = &begin[__ndx];					\
-	__db_hashlookup(begin, type, field, elt, __entp, n, hash, cmp);	\
+	HASHLOOKUP(begin, type, field, elt, __entp, n, hash, cmp);	\
 	SH_TAILQ_REMOVE(__bucket, __entp, field, type);			\
 }
 
 /*
- * __db_hashremove_el --
+ * HASHREMOVE_EL --
  *	Given the object "obj" in the table, remove it.
  * begin: address of the beginning of the hash table.
  * type: the structure type of the elements that are linked in each bucket.
@@ -96,7 +96,7 @@ typedef	SH_TAILQ_HEAD(hash_head) DB_HASHTAB;
  * nelems: the number of buckets in the hash table.
  * hash_func: the hash function that operates on elements of the type of elt
  */
-#define	__db_hashremove_el(begin, type, field, obj, n, hash) {		\
+#define	HASHREMOVE_EL(begin, type, field, obj, n, hash) {		\
 	u_int32_t __ndx;						\
 	DB_HASHTAB *__bucket;						\
 									\
diff --git a/db2/include/hash_ext.h b/db2/include/hash_ext.h
index 5ae63dc6ad..32788c7b8a 100644
--- a/db2/include/hash_ext.h
+++ b/db2/include/hash_ext.h
@@ -1,6 +1,7 @@
 /* Do not edit: automatically built by dist/distrib. */
 int __ham_open __P((DB *, DB_INFO *));
 int  __ham_close __P((DB *));
+int __ham_c_iclose __P((DB *, DBC *));
 int __ham_expand_table __P((HTAB *));
 u_int32_t __ham_call_hash __P((HTAB *, u_int8_t *, int32_t));
 int __ham_init_dbt __P((DBT *, u_int32_t, void **, u_int32_t *));
@@ -96,7 +97,7 @@ 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));
+int __bucket_to_page __P((HTAB *, int));
 #endif
 void __ham_init_ovflpages __P((HTAB *));
 int __ham_get_cpage __P((HTAB *, HASH_CURSOR *, db_lockmode_t));
diff --git a/db2/include/lock.h b/db2/include/lock.h
index 18d29e8740..8f9e81c0fa 100644
--- a/db2/include/lock.h
+++ b/db2/include/lock.h
@@ -4,13 +4,19 @@
  * Copyright (c) 1996, 1997
  *	Sleepycat Software.  All rights reserved.
  *
- *	@(#)lock.h	10.7 (Sleepycat) 7/29/97
+ *	@(#)lock.h	10.8 (Sleepycat) 9/23/97
  */
 
 typedef struct __db_lockobj	DB_LOCKOBJ;
 
 #define DB_DEFAULT_LOCK_FILE	"__db_lock.share"
 #define DB_LOCK_DEFAULT_N	5000
+
+/*
+ * The locker id space is divided between the transaction manager and the lock
+ * manager.  Lockid's start at 0 and go to DB_LOCK_MAXID.  Txn Id's start at
+ * DB_LOCK_MAXID + 1 and go up to TXN_INVALID.
+ */
 #define DB_LOCK_MAXID		0x7fffffff
 
 /*
diff --git a/db2/include/log.h b/db2/include/log.h
index 970dfd153a..a9c82fa04d 100644
--- a/db2/include/log.h
+++ b/db2/include/log.h
@@ -4,7 +4,7 @@
  * Copyright (c) 1996, 1997
  *	Sleepycat Software.  All rights reserved.
  *
- *	@(#)log.h	10.8 (Sleepycat) 8/18/97
+ *	@(#)log.h	10.9 (Sleepycat) 9/23/97
  */
 
 #ifndef _LOG_H_
@@ -30,11 +30,11 @@ struct __log_persist;	typedef struct __log_persist LOGP;
 /* Macros to lock/unlock the region and threads. */
 #define	LOCK_LOGTHREAD(dblp)						\
 	if (F_ISSET(dblp, DB_AM_THREAD))				\
-		(void)__db_mutex_lock(&(dblp)->mutex, -1,		\
+		(void)__db_mutex_lock((dblp)->mutexp, -1,		\
 		    (dblp)->dbenv == NULL ? NULL : (dblp)->dbenv->db_yield)
 #define	UNLOCK_LOGTHREAD(dblp)						\
 	if (F_ISSET(dblp, DB_AM_THREAD))				\
-		(void)__db_mutex_unlock(&(dblp)->mutex, -1);
+		(void)__db_mutex_unlock((dblp)->mutexp, -1);
 #define	LOCK_LOGREGION(dblp)						\
 	(void)__db_mutex_lock(&((RLAYOUT *)(dblp)->lp)->lock,		\
 	    (dblp)->fd, (dblp)->dbenv == NULL ? NULL : (dblp)->dbenv->db_yield)
@@ -56,7 +56,7 @@ typedef	struct __db_entry {
  */
 struct __db_log {
 /* These fields need to be protected for multi-threaded support. */
-	db_mutex_t	mutex;		/* Mutex for thread protection. */
+	db_mutex_t	*mutexp;	/* Mutex for thread protection. */
 
 	DB_ENTRY *dbentry;		/* Recovery file-id mapping. */
 #define	DB_GROW_SIZE	64
@@ -86,6 +86,8 @@ struct __db_log {
 	void     *addr;			/* Address of shalloc() region. */
 	int	  fd;			/* Region file descriptor. */
 
+	char	 *dir;			/* Directory argument. */
+
 	u_int32_t flags;		/* Support the DB_AM_XXX flags. */
 };
 
diff --git a/db2/include/log_ext.h b/db2/include/log_ext.h
index d5c9dd6e72..bc63d9dac8 100644
--- a/db2/include/log_ext.h
+++ b/db2/include/log_ext.h
@@ -1,6 +1,6 @@
 /* Do not edit: automatically built by dist/distrib. */
-int __log_find __P((DB_ENV *, LOG *, int *));
-int __log_valid __P((DB_ENV *, LOG *, int));
+int __log_find __P((DB_LOG *, int *));
+int __log_valid __P((DB_LOG *, LOG *, int));
 int __log_register_log
     __P((DB_LOG *, DB_TXN *, DB_LSN *, u_int32_t,
     DBT *, DBT *, u_int32_t, DBTYPE));
@@ -18,7 +18,7 @@ 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_name __P((DB_ENV *, int, char **));
+int __log_name __P((DB_LOG *, int, char **));
 int __log_register_recover
     __P((DB_LOG *, DBT *, DB_LSN *, int, void *));
 int __log_unregister_recover
diff --git a/db2/include/mp.h b/db2/include/mp.h
index 1fe0c752a9..3b71774484 100644
--- a/db2/include/mp.h
+++ b/db2/include/mp.h
@@ -4,7 +4,7 @@
  * Copyright (c) 1996, 1997
  *	Sleepycat Software.  All rights reserved.
  *
- *	@(#)mp.h	10.15 (Sleepycat) 8/29/97
+ *	@(#)mp.h	10.16 (Sleepycat) 9/23/97
  */
 
 struct __bh;		typedef struct __bh BH;
@@ -99,7 +99,7 @@ struct __mpoolfile;	typedef struct __mpoolfile MPOOLFILE;
  */
 struct __db_mpool {
 /* These fields need to be protected for multi-threaded support. */
-	db_mutex_t	mutex;		/* Structure lock. */
+	db_mutex_t	*mutexp;	/* Structure lock. */
 
 					/* List of pgin/pgout routines. */
 	LIST_HEAD(__db_mpregh, __db_mpreg) dbregq;
@@ -145,7 +145,7 @@ struct __db_mpreg {
  */
 struct __db_mpoolfile {
 /* These fields need to be protected for multi-threaded support. */
-	db_mutex_t	mutex;		/* Structure lock. */
+	db_mutex_t	*mutexp;	/* Structure lock. */
 
 	int	   fd;			/* Underlying file descriptor. */
 
diff --git a/db2/include/shqueue.h b/db2/include/shqueue.h
index c3e2f4aecc..c596d33e92 100644
--- a/db2/include/shqueue.h
+++ b/db2/include/shqueue.h
@@ -1,38 +1,11 @@
-/*
- * Copyright (c) 1991, 1993
- *	The Regents of the University of California.  All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- *    must display the following acknowledgement:
- *	This product includes software developed by the University of
- *	California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
- *    may be used to endorse or promote products derived from this software
- *    without specific prior written permission.
+/*-
+ * See the file LICENSE for redistribution information.
  *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
+ * Copyright (c) 1996, 1997
+ *	Sleepycat Software.  All rights reserved.
  *
- *	@(#)shqueue.h	8.11 (Sleepycat) 7/27/97
+ *	@(#)shqueue.h	8.12 (Sleepycat) 9/10/97
  */
-
 #ifndef	_SYS_SHQUEUE_H_
 #define	_SYS_SHQUEUE_H_
 
diff --git a/db2/include/txn.h b/db2/include/txn.h
index f4e0999b36..8bb3976c1c 100644
--- a/db2/include/txn.h
+++ b/db2/include/txn.h
@@ -4,7 +4,7 @@
  * Copyright (c) 1996, 1997
  *	Sleepycat Software.  All rights reserved.
  *
- *	@(#)txn.h	10.6 (Sleepycat) 7/29/97
+ *	@(#)txn.h	10.10 (Sleepycat) 9/23/97
  */
 #ifndef	_TXN_H_
 #define	_TXN_H_
@@ -14,8 +14,9 @@
  * the region is always created group RW of the group owning the directory.
  */
 #define	DEFAULT_TXN_FILE	"__db_txn.share"
+/* TXN_MINIMUM = (DB_LOCK_MAXID + 1) but this makes compilers complain. */
+#define TXN_MINIMUM		0x80000000
 #define	TXN_INVALID           	0xffffffff /* Maximum number of txn ids. */
-#define TXN_MINIMUM		0x80000000 /* First transaction id */
 
 /*
  * Transaction type declarations.
@@ -36,6 +37,7 @@ typedef struct __txn_detail {
 #define	TXN_ABORTED	2
 #define	TXN_PREPARED	3
 	u_int32_t status;		/* status of the transaction */
+	SH_TAILQ_ENTRY	links;		/* free/active list */
 } TXN_DETAIL;
 
 /*
@@ -45,7 +47,7 @@ typedef struct __txn_detail {
  */
 struct __db_txnmgr {
 /* These fields need to be protected for multi-threaded support. */
-	db_mutex_t	mutex;		/* Synchronization. */
+	db_mutex_t	*mutexp;	/* Synchronization. */
 					/* list of active transactions */
 	TAILQ_HEAD(_chain, __db_txn)	txn_chain;
 
@@ -57,11 +59,14 @@ struct __db_txnmgr {
 	u_int		 flags;		/* DB_TXN_NOSYNC, DB_THREAD */
 	size_t		 reg_size;	/* how large we think the region is */
 	DB_TXNREGION	*region;	/* address of shared memory region */
+	void		*mem;		/* address of the shalloc space */
 };
 
 /*
  * Layout of the shared memory region.
- *
+ * The region consists of a DB_TXNREGION structure followed by a large
+ * pool of shalloc'd memory which is used to hold TXN_DETAIL structures
+ * and thread mutexes (which are dynamically allocated).
  */
 struct __db_txnregion {
 	RLAYOUT		hdr;		/* Shared memory region header. */
@@ -69,7 +74,6 @@ struct __db_txnregion {
 	u_int32_t	version;	/* version number */
 	u_int32_t	maxtxns;	/* maximum number of active txns */
 	u_int32_t	last_txnid;	/* last transaction id given out */
-	u_int32_t	free_txn;	/* head of transaction free list */
 	DB_LSN		pending_ckp;	/* last checkpoint did not finish */
 	DB_LSN		last_ckp;	/* lsn of the last checkpoint */
 	time_t		time_ckp;	/* time of last checkpoint */
@@ -78,20 +82,25 @@ struct __db_txnregion {
 	u_int32_t	naborts;	/* number of aborted transactions */
 	u_int32_t	ncommits;	/* number of committed transactions */
 	u_int32_t	nbegins;	/* number of begun transactions */
-	TXN_DETAIL	table[1];	/* array of TXN structures */
+	SH_TAILQ_HEAD(_active) active_txn;	/* active transaction list */
 };
 
+/*
+ * Make the region large enough to hold N  transaction detail structures
+ * plus some space to hold thread handles and the beginning of the shalloc
+ * region.
+ */
 #define	TXN_REGION_SIZE(N)						\
-			(sizeof(DB_TXNREGION) + N * sizeof(DB_TXN))
+	(sizeof(DB_TXNREGION) + N * sizeof(TXN_DETAIL) + 1000)
 
 /* Macros to lock/unlock the region and threads. */
 #define	LOCK_TXNTHREAD(tmgrp)						\
 	if (F_ISSET(tmgrp, DB_THREAD))					\
-		(void)__db_mutex_lock(&(tmgrp)->mutex, -1,		\
+		(void)__db_mutex_lock((tmgrp)->mutexp, -1,		\
 		    (tmgrp)->dbenv == NULL ? NULL : (tmgrp)->dbenv->db_yield)
 #define	UNLOCK_TXNTHREAD(tmgrp)						\
 	if (F_ISSET(tmgrp, DB_THREAD))					\
-		(void)__db_mutex_unlock(&(tmgrp)->mutex, -1)
+		(void)__db_mutex_unlock((tmgrp)->mutexp, -1)
 
 #define	LOCK_TXNREGION(tmgrp)						\
 	(void)__db_mutex_lock(&(tmgrp)->region->hdr.lock,(tmgrp)->fd,	\
diff --git a/db2/lock/lock.c b/db2/lock/lock.c
index 8fc91334a7..a2a3b208f2 100644
--- a/db2/lock/lock.c
+++ b/db2/lock/lock.c
@@ -8,7 +8,7 @@
 #include "config.h"
 
 #ifndef lint
-static const char sccsid[] = "@(#)lock.c	10.31 (Sleepycat) 8/17/97";
+static const char sccsid[] = "@(#)lock.c	10.36 (Sleepycat) 9/24/97";
 #endif /* not lint */
 
 #ifndef NO_SYSTEM_INCLUDES
@@ -201,7 +201,7 @@ lock_open(path, flags, mode, dbenv, ltp)
 	 * Create the lock table structure.
 	 */
 	if ((lt = (DB_LOCKTAB *)calloc(1, sizeof(DB_LOCKTAB))) == NULL) {
-		__db_err(dbenv, "%s", strerror(errno));
+		__db_err(dbenv, "%s", strerror(ENOMEM));
 		return (ENOMEM);
 	}
 	lt->dbenv = dbenv;
@@ -319,8 +319,10 @@ lock_vec(lt, locker, flags, list, nlist, elistp)
 		case DB_LOCK_GET:
 			ret = __lock_get_internal(lt, locker, flags,
 			    list[i].obj, list[i].mode, &lp);
-			if (ret == 0)
+			if (ret == 0) {
 				list[i].lock = LOCK_TO_OFFSET(lt, lp);
+				lt->region->nrequests++;
+			}
 			break;
 		case DB_LOCK_PUT:
 			lp = OFFSET_TO_LOCK(lt, list[i].lock);
@@ -351,7 +353,7 @@ lock_vec(lt, locker, flags, list, nlist, elistp)
 		case DB_LOCK_PUT_OBJ:
 
 			/* Look up the object in the hash table. */
-			__db_hashlookup(lt->hashtab, __db_lockobj, links,
+			HASHLOOKUP(lt->hashtab, __db_lockobj, links,
 			    list[i].obj, sh_obj, lt->region->table_size,
 			    __lock_ohash, __lock_cmp);
 			if (sh_obj == NULL) {
@@ -596,8 +598,8 @@ __lock_put_internal(lt, lockp, do_all)
 
 	/* Check if object should be reclaimed. */
 	if (SH_TAILQ_FIRST(&sh_obj->holders, __db_lock) == NULL) {
-		__db_hashremove_el(lt->hashtab, __db_lockobj, links, sh_obj,
-		    lt->region->table_size, __lock_lhash);
+		HASHREMOVE_EL(lt->hashtab, __db_lockobj,
+		    links, sh_obj, lt->region->table_size, __lock_lhash);
 		__db_shalloc_free(lt->mem, SH_DBT_PTR(&sh_obj->lockobj));
 		SH_TAILQ_INSERT_HEAD(&lt->region->free_objs, sh_obj, links,
 		    __db_lockobj);
@@ -676,8 +678,12 @@ __lock_get_internal(lt, locker, flags, obj, lock_mode, lockp)
 	 * Now we have a lock and an object and we need to see if we should
 	 * grant the lock.  We use a FIFO ordering so we can only grant a
 	 * new lock if it does not conflict with anyone on the holders list
-	 * OR anyone on the waiters list.  In case of conflict, we put the
-	 * new lock on the end of the waiters list.
+	 * OR anyone on the waiters list.  The reason that we don't grant if
+	 * there's a conflict is that this can lead to starvation (a writer
+	 * waiting on a popularly read item will never ben granted).  The
+	 * downside of this is that a waiting reader can prevent an upgrade
+	 * from reader to writer, which is not uncommon.  In case of conflict,
+	 * we put the new lock on the end of the waiters list.
 	 */
 	for (lp = SH_TAILQ_FIRST(&sh_obj->holders, __db_lock);
 	    lp != NULL;
@@ -1042,7 +1048,7 @@ __lock_dump_locker(lt, op)
 
 	ptr = SH_DBT_PTR(&op->lockobj);
 	memcpy(&locker, ptr, sizeof(u_int32_t));
-	printf("L %lu", (u_long)locker);
+	printf("L %lx", (u_long)locker);
 
 	lp = SH_LIST_FIRST(&op->heldby, __db_lock);
 	if (lp == NULL) {
@@ -1095,7 +1101,7 @@ __lock_is_locked(lt, locker, dbt, mode)
 	lrp = lt->region;
 
 	/* Look up the object in the hash table. */
-	__db_hashlookup(lt->hashtab, __db_lockobj, links,
+	HASHLOOKUP(lt->hashtab, __db_lockobj, links,
 	    dbt, sh_obj, lrp->table_size, __lock_ohash, __lock_cmp);
 	if (sh_obj == NULL)
 		return (0);
@@ -1171,7 +1177,7 @@ __lock_printlock(lt, lp, ispgno)
 		stat = "UNKNOWN";
 		break;
 	}
-	printf("\t%lu\t%s\t%lu\t%s\t",
+	printf("\t%lx\t%s\t%lu\t%s\t",
 	    (u_long)lp->holder, mode, (u_long)lp->refcount, stat);
 
 	lockobj = (DB_LOCKOBJ *)((u_int8_t *)lp + lp->obj);
@@ -1243,11 +1249,11 @@ __lock_getobj(lt, locker, dbt, type, objp)
 
 	/* Look up the object in the hash table. */
 	if (type == DB_LOCK_OBJTYPE) {
-		__db_hashlookup(lt->hashtab, __db_lockobj, links, dbt, sh_obj,
+		HASHLOOKUP(lt->hashtab, __db_lockobj, links, dbt, sh_obj,
 		    lrp->table_size, __lock_ohash, __lock_cmp);
 		obj_size = dbt->size;
 	} else {
-		__db_hashlookup(lt->hashtab, __db_lockobj, links, locker,
+		HASHLOOKUP(lt->hashtab, __db_lockobj, links, locker,
 		    sh_obj, lrp->table_size, __lock_locker_hash,
 		    __lock_locker_cmp);
 		obj_size = sizeof(locker);
@@ -1288,8 +1294,8 @@ __lock_getobj(lt, locker, dbt, type, objp)
 		sh_obj->lockobj.size = obj_size;
 		sh_obj->lockobj.off = SH_PTR_TO_OFF(&sh_obj->lockobj, p);
 
-		__db_hashinsert(lt->hashtab, __db_lockobj, links, sh_obj,
-		    lrp->table_size, __lock_lhash);
+		HASHINSERT(lt->hashtab,
+		    __db_lockobj, links, sh_obj, lrp->table_size, __lock_lhash);
 
 		if (type == DB_LOCK_LOCKER)
 			lrp->nlockers++;
@@ -1325,8 +1331,8 @@ __lock_freeobj(lt, obj)
 	DB_LOCKTAB *lt;
 	DB_LOCKOBJ *obj;
 {
-	__db_hashremove_el(lt->hashtab, __db_lockobj, links,
-	    obj, lt->region->table_size, __lock_lhash);
+	HASHREMOVE_EL(lt->hashtab,
+	    __db_lockobj, links, obj, lt->region->table_size, __lock_lhash);
 	__db_shalloc_free(lt->mem, SH_DBT_PTR(&obj->lockobj));
 	SH_TAILQ_INSERT_HEAD(&lt->region->free_objs, obj, links, __db_lockobj);
 }
diff --git a/db2/lock/lock_deadlock.c b/db2/lock/lock_deadlock.c
index f753958b21..f947f901c3 100644
--- a/db2/lock/lock_deadlock.c
+++ b/db2/lock/lock_deadlock.c
@@ -11,7 +11,7 @@
 static const char copyright[] =
 "@(#) Copyright (c) 1997\n\
 	Sleepycat Software Inc.  All rights reserved.\n";
-static const char sccsid[] = "@(#)lock_deadlock.c	10.20 (Sleepycat) 8/21/97";
+static const char sccsid[] = "@(#)lock_deadlock.c	10.21 (Sleepycat) 9/6/97";
 #endif
 
 #ifndef NO_SYSTEM_INCLUDES
@@ -300,8 +300,8 @@ retry:	count = lt->region->nlockers;
 			for (lp = SH_TAILQ_FIRST(&op->holders, __db_lock);
 			    lp != NULL;
 			    lp = SH_TAILQ_NEXT(lp, links, __db_lock)) {
-				if ((__set_errno(__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;
@@ -472,8 +472,7 @@ __dd_debug(dbenv, idmap, bitmap, nlockers)
 	 * Alloc space to print 10 bytes per item waited on.
 	 */
 	if ((msgbuf = (char *)malloc((nlockers + 1) * 10 + 64)) == NULL) {
-		__set_errno(ENOMEM);
-		__db_err(dbenv, "%s", strerror(errno));
+		__db_err(dbenv, "%s", strerror(ENOMEM));
 		return;
 	}
 
diff --git a/db2/log/log.c b/db2/log/log.c
index d3e5183588..893c1ee402 100644
--- a/db2/log/log.c
+++ b/db2/log/log.c
@@ -7,7 +7,7 @@
 #include "config.h"
 
 #ifndef lint
-static const char sccsid[] = "@(#)log.c	10.25 (Sleepycat) 8/27/97";
+static const char sccsid[] = "@(#)log.c	10.27 (Sleepycat) 9/23/97";
 #endif /* not lint */
 
 #ifndef NO_SYSTEM_INCLUDES
@@ -29,7 +29,7 @@ static const char sccsid[] = "@(#)log.c	10.25 (Sleepycat) 8/27/97";
 #include "txn_auto.h"
 #include "common_ext.h"
 
-static int __log_recover __P((DB_ENV *, DB_LOG *));
+static int __log_recover __P((DB_LOG *));
 
 /*
  * log_open --
@@ -70,14 +70,15 @@ log_open(path, flags, mode, dbenv, lpp)
 	if ((dblp = (DB_LOG *)calloc(1, sizeof(DB_LOG))) == NULL)
 		return (ENOMEM);
 
+	if (path != NULL && (dblp->dir = strdup(path)) == NULL) {
+		free(dblp);
+		return (ENOMEM);
+	}
+
 	dblp->dbenv = dbenv;
 	dblp->lfd = -1;
 	ZERO_LSN(dblp->c_lsn);
 	dblp->c_fd = -1;
-	if (LF_ISSET(DB_THREAD)) {
-		F_SET(dblp, DB_AM_THREAD);
-		(void)__db_mutex_init(&dblp->mutex, -1);
-	}
 
 	/*
 	 * The log region isn't fixed size because we store the registered
@@ -114,7 +115,7 @@ retry:	if (LF_ISSET(DB_CREATE)) {
 
 			newregion = 1;
 		} else if (ret != EEXIST)
-			return (ret);
+			goto err;
 	}
 
 	/* If we didn't or couldn't create the region, try and join it. */
@@ -129,7 +130,7 @@ retry:	if (LF_ISSET(DB_CREATE)) {
 			(void)__db_sleep(1, 0);
 			goto retry;
 		}
-		return (ret);
+		goto err;
 	}
 
 	/* Set up the common information. */
@@ -137,19 +138,49 @@ retry:	if (LF_ISSET(DB_CREATE)) {
 	dblp->addr = (u_int8_t *)dblp->maddr + sizeof(LOG);
 	dblp->fd = fd;
 
+	/* Initialize thread information. */
+	if (LF_ISSET(DB_THREAD)) {
+		F_SET(dblp, DB_AM_THREAD);
+
+		if (!newregion)
+			LOCK_LOGREGION(dblp);
+		if ((ret = __db_shalloc(dblp->addr,
+		    sizeof(db_mutex_t), MUTEX_ALIGNMENT, &dblp->mutexp)) == 0)
+			(void)__db_mutex_init(dblp->mutexp, -1);
+		if (!newregion)
+			UNLOCK_LOGREGION(dblp);
+		if (ret != 0) {
+			(void)log_close(dblp);
+			if (newregion)
+				(void)log_unlink(path, 1, dbenv);
+			return (ret);
+		}
+	}
+
 	/*
 	 * If doing recovery, try and recover any previous log files
 	 * before releasing the lock.
 	 */
 	if (newregion) {
-		if ((ret = __log_recover(dbenv, dblp)) != 0) {
-			log_unlink(path, 1, dbenv);
+		ret = __log_recover(dblp);
+		UNLOCK_LOGREGION(dblp);
+
+		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);
+
 }
 
 /*
@@ -157,8 +188,7 @@ retry:	if (LF_ISSET(DB_CREATE)) {
  *	Recover a log.
  */
 static int
-__log_recover(dbenv, dblp)
-	DB_ENV *dbenv;
+__log_recover(dblp)
 	DB_LOG *dblp;
 {
 	DBT dbt;
@@ -173,14 +203,14 @@ __log_recover(dbenv, dblp)
 	 * Find a log file.  If none exist, we simply return, leaving
 	 * everything initialized to a new log.
 	 */
-	if ((ret = __log_find(dbenv, lp, &cnt)) != 0)
+	if ((ret = __log_find(dblp, &cnt)) != 0)
 		return (ret);
 	if (cnt == 0)
 		return (0);
 
 	/* We have a log file name, find the last one. */
 	while (cnt < MAXLFNAME)
-		if (__log_valid(dbenv, lp, ++cnt) != 0) {
+		if (__log_valid(dblp, lp, ++cnt) != 0) {
 			--cnt;
 			break;
 		}
@@ -263,7 +293,7 @@ __log_recover(dbenv, dblp)
 		lp->c_lsn.offset = 0;
 	}
 
-	__db_err(dbenv,
+	__db_err(dblp->dbenv,
 	    "Recovering the log: last valid LSN: file: %lu offset %lu",
 	    (u_long)lp->lsn.file, (u_long)lp->lsn.offset);
 
@@ -277,12 +307,11 @@ __log_recover(dbenv, dblp)
  * __log_find --
  *	Try to find a log file.
  *
- * PUBLIC: int __log_find __P((DB_ENV *, LOG *, int *));
+ * PUBLIC: int __log_find __P((DB_LOG *, int *));
  */
 int
-__log_find(dbenv, lp, valp)
-	DB_ENV *dbenv;
-	LOG *lp;
+__log_find(dblp, valp)
+	DB_LOG *dblp;
 	int *valp;
 {
 	int cnt, fcnt, logval, ret;
@@ -290,7 +319,7 @@ __log_find(dbenv, lp, valp)
 	char **names, *p, *q;
 
 	/* Find the directory name. */
-	if ((ret = __log_name(dbenv, 1, &p)) != 0)
+	if ((ret = __log_name(dblp, 1, &p)) != 0)
 		return (ret);
 	if ((q = __db_rpath(p)) == NULL)
 		dir = PATH_DOT;
@@ -300,7 +329,7 @@ __log_find(dbenv, lp, valp)
 	}
 
 	/* Get the list of file names. */
-	ret = __db_dir(dbenv, dir, &names, &fcnt);
+	ret = __db_dir(dblp->dbenv, dir, &names, &fcnt);
 	FREES(p);
 	if (ret != 0)
 		return (ret);
@@ -314,14 +343,14 @@ __log_find(dbenv, lp, valp)
 		if (strncmp(names[cnt], "log.", sizeof("log.") - 1) == 0) {
 			logval = atoi(names[cnt] + 4);
 			if (logval != 0 &&
-			    __log_valid(dbenv, lp, logval) == 0) {
+			    __log_valid(dblp, dblp->lp, logval) == 0) {
 				*valp = logval;
 				break;
 			}
 		}
 
 	/* Discard the list. */
-	__db_dirf(dbenv, names, fcnt);
+	__db_dirf(dblp->dbenv, names, fcnt);
 
 	return (ret);
 }
@@ -330,11 +359,11 @@ __log_find(dbenv, lp, valp)
  * log_valid --
  *	Validate a log file.
  *
- * PUBLIC: int __log_valid __P((DB_ENV *, LOG *, int));
+ * PUBLIC: int __log_valid __P((DB_LOG *, LOG *, int));
  */
 int
-__log_valid(dbenv, lp, cnt)
-	DB_ENV *dbenv;
+__log_valid(dblp, lp, cnt)
+	DB_LOG *dblp;
 	LOG *lp;
 	int cnt;
 {
@@ -343,7 +372,7 @@ __log_valid(dbenv, lp, cnt)
 	int fd, ret;
 	char *p;
 
-	if ((ret = __log_name(dbenv, cnt, &p)) != 0)
+	if ((ret = __log_name(dblp, cnt, &p)) != 0)
 		return (ret);
 
 	fd = -1;
@@ -357,7 +386,7 @@ __log_valid(dbenv, lp, cnt)
 			ret = EIO;
 		if (fd != -1) {
 			(void)__db_close(fd);
-			__db_err(dbenv,
+			__db_err(dblp->dbenv,
 			    "Ignoring log file: %s: %s", p, strerror(ret));
 		}
 		goto err;
@@ -365,14 +394,14 @@ __log_valid(dbenv, lp, cnt)
 	(void)__db_close(fd);
 
 	if (persist.magic != DB_LOGMAGIC) {
-		__db_err(dbenv,
+		__db_err(dblp->dbenv,
 		    "Ignoring log file: %s: magic number %lx, not %lx",
 		    p, (u_long)persist.magic, (u_long)DB_LOGMAGIC);
 		ret = EINVAL;
 		goto err;
 	}
 	if (persist.version < DB_LOGOLDVER || persist.version > DB_LOGVERSION) {
-		__db_err(dbenv,
+		__db_err(dblp->dbenv,
 		    "Ignoring log file: %s: unsupported log version %lu",
 		    p, (u_long)persist.version);
 		ret = EINVAL;
@@ -401,6 +430,13 @@ log_close(dblp)
 
 	ret = 0;
 
+	/* Discard the per-thread pointer. */
+	if (dblp->mutexp != NULL) {
+		LOCK_LOGREGION(dblp);
+		__db_shalloc_free(dblp->addr, dblp->mutexp);
+		UNLOCK_LOGREGION(dblp);
+	}
+
 	/* Close the region. */
 	if ((t_ret =
 	    __db_rclose(dblp->dbenv, dblp->fd, dblp->maddr)) != 0 && ret == 0)
@@ -414,10 +450,12 @@ log_close(dblp)
 	if (dblp->c_fd != -1 &&
 	    (t_ret = __db_close(dblp->c_fd)) != 0 && ret == 0)
 		ret = t_ret;
-
-	/* Free the structure. */
 	if (dblp->dbentry != NULL)
 		FREE(dblp->dbentry, (dblp->dbentry_cnt * sizeof(DB_ENTRY)));
+	if (dblp->dir != NULL)
+		FREES(dblp->dir);
+
+	/* Free the structure. */
 	FREE(dblp, sizeof(DB_LOG));
 
 	return (ret);
diff --git a/db2/log/log_archive.c b/db2/log/log_archive.c
index 0d6c3f2bea..6904a2c726 100644
--- a/db2/log/log_archive.c
+++ b/db2/log/log_archive.c
@@ -8,7 +8,7 @@
 #include "config.h"
 
 #ifndef lint
-static const char sccsid[] = "@(#)log_archive.c	10.23 (Sleepycat) 8/23/97";
+static const char sccsid[] = "@(#)log_archive.c	10.26 (Sleepycat) 9/23/97";
 #endif /* not lint */
 
 #ifndef NO_SYSTEM_INCLUDES
@@ -27,18 +27,18 @@ static const char sccsid[] = "@(#)log_archive.c	10.23 (Sleepycat) 8/23/97";
 #include "clib_ext.h"
 #include "common_ext.h"
 
-static int absname __P((char *, char *, char **));
-static int build_data __P((DB_LOG *, char *, char ***, void *(*)(size_t)));
-static int cmpfunc __P((const void *, const void *));
-static int usermem __P((char ***, void *(*)(size_t)));
+static int __absname __P((char *, char *, char **));
+static int __build_data __P((DB_LOG *, char *, char ***, void *(*)(size_t)));
+static int __cmpfunc __P((const void *, const void *));
+static int __usermem __P((char ***, void *(*)(size_t)));
 
 /*
  * log_archive --
  *	Supporting function for db_archive(1).
  */
 int
-log_archive(logp, listp, flags, db_malloc)
-	DB_LOG *logp;
+log_archive(dblp, listp, flags, db_malloc)
+	DB_LOG *dblp;
 	char ***listp;
 	int flags;
 	void *(*db_malloc) __P((size_t));
@@ -54,10 +54,10 @@ log_archive(logp, listp, flags, db_malloc)
 #define	OKFLAGS	(DB_ARCH_ABS | DB_ARCH_DATA | DB_ARCH_LOG)
 	if (flags != 0) {
 		if ((ret =
-		    __db_fchk(logp->dbenv, "log_archive", flags, OKFLAGS)) != 0)
+		    __db_fchk(dblp->dbenv, "log_archive", flags, OKFLAGS)) != 0)
 			return (ret);
 		if ((ret =
-		    __db_fcchk(logp->dbenv,
+		    __db_fcchk(dblp->dbenv,
 		        "log_archive", flags, DB_ARCH_DATA, DB_ARCH_LOG)) != 0)
 			return (ret);
 	}
@@ -68,7 +68,7 @@ log_archive(logp, listp, flags, db_malloc)
 	 * but that's just not possible.
 	 */
 	if (LF_ISSET(DB_ARCH_ABS)) {
-		__set_errno(0);
+		__set_errno (0);
 		if ((pref = getcwd(buf, sizeof(buf))) == NULL)
 			return (errno == 0 ? ENOMEM : errno);
 	} else
@@ -76,19 +76,19 @@ log_archive(logp, listp, flags, db_malloc)
 
 	switch (LF_ISSET(~DB_ARCH_ABS)) {
 	case DB_ARCH_DATA:
-		return (build_data(logp, pref, listp, db_malloc));
+		return (__build_data(dblp, pref, listp, db_malloc));
 	case DB_ARCH_LOG:
 		memset(&rec, 0, sizeof(rec));
-		if (F_ISSET(logp, DB_AM_THREAD))
+		if (F_ISSET(dblp, DB_AM_THREAD))
 			F_SET(&rec, DB_DBT_MALLOC);
-		if ((ret = log_get(logp, &stable_lsn, &rec, DB_LAST)) != 0)
+		if ((ret = log_get(dblp, &stable_lsn, &rec, DB_LAST)) != 0)
 			return (ret);
-		if (F_ISSET(logp, DB_AM_THREAD))
+		if (F_ISSET(dblp, DB_AM_THREAD))
 			free(rec.data);
 		fnum = stable_lsn.file;
 		break;
 	case 0:
-		if ((ret = __log_findckp(logp, &stable_lsn)) != 0) {
+		if ((ret = __log_findckp(dblp, &stable_lsn)) != 0) {
 			if (ret != DB_NOTFOUND)
 				return (ret);
 			*listp = NULL;
@@ -108,7 +108,7 @@ log_archive(logp, listp, flags, db_malloc)
 
 	/* Build an array of the file names. */
 	for (n = 0; fnum > 0; --fnum) {
-		if ((ret = __log_name(logp->dbenv, fnum, &name)) != 0)
+		if ((ret = __log_name(dblp, fnum, &name)) != 0)
 			goto err;
 		if (__db_exists(name, NULL) != 0)
 			break;
@@ -123,7 +123,7 @@ log_archive(logp, listp, flags, db_malloc)
 		}
 
 		if (LF_ISSET(DB_ARCH_ABS)) {
-			if ((ret = absname(pref, name, &array[n])) != 0)
+			if ((ret = __absname(pref, name, &array[n])) != 0)
 				goto err;
 			FREES(name);
 		} else if ((p = __db_rpath(name)) != NULL) {
@@ -146,10 +146,10 @@ log_archive(logp, listp, flags, db_malloc)
 	}
 
 	/* Sort the list. */
-	qsort(array, (size_t)n, sizeof(char *), cmpfunc);
+	qsort(array, (size_t)n, sizeof(char *), __cmpfunc);
 
 	/* Rework the memory. */
-	if ((ret = usermem(&array, db_malloc)) != 0)
+	if ((ret = __usermem(&array, db_malloc)) != 0)
 		goto err;
 
 	*listp = array;
@@ -164,12 +164,12 @@ err:	if (array != NULL) {
 }
 
 /*
- * build_data --
+ * __build_data --
  *	Build a list of datafiles for return.
  */
 static int
-build_data(logp, pref, listp, db_malloc)
-	DB_LOG *logp;
+__build_data(dblp, pref, listp, db_malloc)
+	DB_LOG *dblp;
 	char *pref, ***listp;
 	void *(*db_malloc) __P((size_t));
 {
@@ -187,19 +187,19 @@ build_data(logp, pref, listp, db_malloc)
 	array[0] = NULL;
 
 	memset(&rec, 0, sizeof(rec));
-	if (F_ISSET(logp, DB_AM_THREAD))
+	if (F_ISSET(dblp, DB_AM_THREAD))
 		F_SET(&rec, DB_DBT_MALLOC);
-	for (n = 0, ret = log_get(logp, &lsn, &rec, DB_FIRST);
-	    ret == 0; ret = log_get(logp, &lsn, &rec, DB_NEXT)) {
+	for (n = 0, ret = log_get(dblp, &lsn, &rec, DB_FIRST);
+	    ret == 0; ret = log_get(dblp, &lsn, &rec, DB_NEXT)) {
 		if (rec.size < sizeof(rectype)) {
 			ret = EINVAL;
-			__db_err(logp->dbenv, "log_archive: bad log record");
+			__db_err(dblp->dbenv, "log_archive: bad log record");
 			goto lg_free;
 		}
 
 		memcpy(&rectype, rec.data, sizeof(rectype));
 		if (rectype != DB_log_register) {
-			if (F_ISSET(logp, DB_AM_THREAD)) {
+			if (F_ISSET(dblp, DB_AM_THREAD)) {
 				free(rec.data);
 				rec.data = NULL;
 			}
@@ -207,7 +207,7 @@ build_data(logp, pref, listp, db_malloc)
 		}
 		if ((ret = __log_register_read(rec.data, &argp)) != 0) {
 			ret = EINVAL;
-			__db_err(logp->dbenv,
+			__db_err(dblp->dbenv,
 			    "log_archive: unable to read log record");
 			goto lg_free;
 		}
@@ -231,7 +231,7 @@ lg_free:		if (F_ISSET(&rec, DB_DBT_MALLOC) && rec.data != NULL)
 		array[++n] = NULL;
 		free(argp);
 
-		if (F_ISSET(logp, DB_AM_THREAD)) {
+		if (F_ISSET(dblp, DB_AM_THREAD)) {
 			free(rec.data);
 			rec.data = NULL;
 		}
@@ -245,7 +245,7 @@ lg_free:		if (F_ISSET(&rec, DB_DBT_MALLOC) && rec.data != NULL)
 	}
 
 	/* Sort the list. */
-	qsort(array, (size_t)n, sizeof(char *), cmpfunc);
+	qsort(array, (size_t)n, sizeof(char *), __cmpfunc);
 
 	/*
 	 * Build the real pathnames, discarding nonexistent files and
@@ -268,7 +268,7 @@ lg_free:		if (F_ISSET(&rec, DB_DBT_MALLOC) && rec.data != NULL)
 		}
 
 		/* Get the real name. */
-		if ((ret = __db_appname(logp->dbenv,
+		if ((ret = __db_appname(dblp->dbenv,
 		    DB_APP_DATA, NULL, array[last], NULL, &real_name)) != 0)
 			goto err2;
 
@@ -284,7 +284,7 @@ lg_free:		if (F_ISSET(&rec, DB_DBT_MALLOC) && rec.data != NULL)
 		FREES(array[last]);
 		array[last] = NULL;
 		if (pref != NULL) {
-			ret = absname(pref, real_name, &array[last]);
+			ret = __absname(pref, real_name, &array[last]);
 			FREES(real_name);
 			if (ret != 0)
 				goto err2;
@@ -302,7 +302,7 @@ lg_free:		if (F_ISSET(&rec, DB_DBT_MALLOC) && rec.data != NULL)
 	array[last] = NULL;
 
 	/* Rework the memory. */
-	if ((ret = usermem(&array, db_malloc)) != 0)
+	if ((ret = __usermem(&array, db_malloc)) != 0)
 		goto err1;
 
 	*listp = array;
@@ -327,11 +327,11 @@ err1:	if (array != NULL) {
 }
 
 /*
- * absname --
+ * __absname --
  *	Return an absolute path name for the file.
  */
 static int
-absname(pref, name, newnamep)
+__absname(pref, name, newnamep)
 	char *pref, *name, **newnamep;
 {
 	size_t l_pref, l_name;
@@ -355,12 +355,12 @@ absname(pref, name, newnamep)
 }
 
 /*
- * usermem --
+ * __usermem --
  *	Create a single chunk of memory that holds the returned information.
  *	If the user has their own malloc routine, use it.
  */
 static int
-usermem(listp, func)
+__usermem(listp, func)
 	char ***listp;
 	void *(*func) __P((size_t));
 {
@@ -406,7 +406,7 @@ usermem(listp, func)
 }
 
 static int
-cmpfunc(p1, p2)
+__cmpfunc(p1, p2)
 	const void *p1, *p2;
 {
 	return (strcmp(*((char **)p1), *((char **)p2)));
diff --git a/db2/log/log_auto.c b/db2/log/log_auto.c
index 59400087ca..ea88a7bff9 100644
--- a/db2/log/log_auto.c
+++ b/db2/log/log_auto.c
@@ -121,7 +121,7 @@ __log_register_print(notused1, dbtp, lsnp, notused3, notused4)
 	notused3 = 0;
 	notused4 = NULL;
 
-	if((ret = __log_register_read(dbtp->data, &argp)) != 0)
+	if ((ret = __log_register_read(dbtp->data, &argp)) != 0)
 		return (ret);
 	printf("[%lu][%lu]log_register: rec: %lu txnid %lx prevlsn [%lu][%lu]\n",
 	    (u_long)lsnp->file,
@@ -269,7 +269,7 @@ __log_unregister_print(notused1, dbtp, lsnp, notused3, notused4)
 	notused3 = 0;
 	notused4 = NULL;
 
-	if((ret = __log_unregister_read(dbtp->data, &argp)) != 0)
+	if ((ret = __log_unregister_read(dbtp->data, &argp)) != 0)
 		return (ret);
 	printf("[%lu][%lu]log_unregister: rec: %lu txnid %lx prevlsn [%lu][%lu]\n",
 	    (u_long)lsnp->file,
diff --git a/db2/log/log_get.c b/db2/log/log_get.c
index 54a58c75fc..3f6df6c33c 100644
--- a/db2/log/log_get.c
+++ b/db2/log/log_get.c
@@ -7,7 +7,7 @@
 #include "config.h"
 
 #ifndef lint
-static const char sccsid[] = "@(#)log_get.c	10.17 (Sleepycat) 8/27/97";
+static const char sccsid[] = "@(#)log_get.c	10.19 (Sleepycat) 9/23/97";
 #endif /* not lint */
 
 #ifndef NO_SYSTEM_INCLUDES
@@ -145,7 +145,7 @@ __log_get(dblp, alsn, dbt, flags, silent)
 		 * Find any log file.  Note, we may have only entered records
 		 * in the buffer, and not yet written a log file.
 		 */
-		if ((ret = __log_find(dblp->dbenv, lp, &cnt)) != 0) {
+		if ((ret = __log_find(dblp, &cnt)) != 0) {
 			__db_err(dblp->dbenv,
 	"log_get: unable to find the first record: no log files found.");
 			goto err2;
@@ -157,7 +157,7 @@ __log_get(dblp, alsn, dbt, flags, silent)
 
 		/* Now go backwards to find the smallest one. */
 		for (; cnt > 1; --cnt)
-			if (__log_valid(dblp->dbenv, NULL, cnt) != 0) {
+			if (__log_valid(dblp, NULL, cnt) != 0) {
 				++cnt;
 				break;
 			}
@@ -223,7 +223,7 @@ retry:
 	 * Acquire a file descriptor.
 	 */
 	if (dblp->c_fd == -1) {
-		if ((ret = __log_name(dblp->dbenv, nlsn.file, &np)) != 0)
+		if ((ret = __log_name(dblp, nlsn.file, &np)) != 0)
 			goto err1;
 		if ((ret = __db_fdopen(np, DB_RDONLY | DB_SEQUENTIAL,
 		    DB_RDONLY | DB_SEQUENTIAL, 0, &dblp->c_fd)) != 0) {
@@ -319,6 +319,7 @@ retry:
 	    &dblp->c_dbt.data, &dblp->c_dbt.ulen, NULL)) != 0)
 		goto err1;
 	free(tbuf);
+	tbuf = NULL;
 
 cksum:	if (hdr.cksum != __ham_func4(dbt->data, dbt->size)) {
 		if (!silent)
diff --git a/db2/log/log_put.c b/db2/log/log_put.c
index db31f9b0e1..225595f33e 100644
--- a/db2/log/log_put.c
+++ b/db2/log/log_put.c
@@ -7,7 +7,7 @@
 #include "config.h"
 
 #ifndef lint
-static const char sccsid[] = "@(#)log_put.c	10.12 (Sleepycat) 8/20/97";
+static const char sccsid[] = "@(#)log_put.c	10.14 (Sleepycat) 9/23/97";
 #endif /* not lint */
 
 #ifndef NO_SYSTEM_INCLUDES
@@ -416,7 +416,7 @@ log_file(dblp, lsn, namep, len)
 
 	LOCK_LOGREGION(dblp);
 
-	ret = __log_name(dblp->dbenv, lsn->file, &p);
+	ret = __log_name(dblp, lsn->file, &p);
 
 	UNLOCK_LOGREGION(dblp);
 
@@ -453,14 +453,14 @@ __log_newfd(dblp)
 
 	/* Get the path of the new file and open it. */
 	dblp->lfname = dblp->lp->lsn.file;
-	if ((ret = __log_name(dblp->dbenv, dblp->lfname, &p)) != 0)
+	if ((ret = __log_name(dblp, dblp->lfname, &p)) != 0)
 		return (ret);
 	if ((ret = __db_fdopen(p,
 	    DB_CREATE | DB_SEQUENTIAL,
 	    DB_CREATE | DB_SEQUENTIAL,
 	    dblp->lp->persist.mode, &dblp->lfd)) != 0)
 		__db_err(dblp->dbenv,
-		    "log_put: %s: %s", p, strerror(errno));
+		    "log_put: %s: %s", p, strerror(ret));
 	FREES(p);
 	return (ret);
 }
@@ -469,16 +469,17 @@ __log_newfd(dblp)
  * __log_name --
  *	Return the log name for a particular file.
  *
- * PUBLIC: int __log_name __P((DB_ENV *, int, char **));
+ * PUBLIC: int __log_name __P((DB_LOG *, int, char **));
  */
 int
-__log_name(dbenv, fn, np)
-	DB_ENV *dbenv;
-	int fn;
-	char **np;
+__log_name(dblp, fileno, namep)
+	DB_LOG *dblp;
+	char **namep;
+	int fileno;
 {
 	char name[sizeof(LFNAME) + 10];
 
-	(void)snprintf(name, sizeof(name), LFNAME, fn);
-	return (__db_appname(dbenv, DB_APP_LOG, NULL, name, NULL, np));
+	(void)snprintf(name, sizeof(name), LFNAME, fileno);
+	return (__db_appname(dblp->dbenv,
+	    DB_APP_LOG, dblp->dir, name, NULL, namep));
 }
diff --git a/db2/log/log_register.c b/db2/log/log_register.c
index 582eab9408..859b1e5bcb 100644
--- a/db2/log/log_register.c
+++ b/db2/log/log_register.c
@@ -7,7 +7,7 @@
 #include "config.h"
 
 #ifndef lint
-static const char sccsid[] = "@(#)log_register.c	10.10 (Sleepycat) 8/20/97";
+static const char sccsid[] = "@(#)log_register.c	10.11 (Sleepycat) 9/15/97";
 #endif /* not lint */
 
 #ifndef NO_SYSTEM_INCLUDES
@@ -190,8 +190,13 @@ log_unregister(dblp, fid)
 	SH_TAILQ_REMOVE(&dblp->lp->fq, fnp, q, __fname);
 	__db_shalloc_free(dblp->addr, fnp);
 
-	/* Remove from the process local table. */
-	__log_rem_logid(dblp, fid);
+	/*
+	 * Remove from the process local table.  If this operation is taking
+	 * place during recovery, then the logid was never added to the table,
+	 * so do not remove it.
+	 */
+	if (!F_ISSET(dblp, DB_AM_RECOVER))
+		__log_rem_logid(dblp, fid);
 
 ret1:	UNLOCK_LOGREGION(dblp);
 
diff --git a/db2/mp/mp_bh.c b/db2/mp/mp_bh.c
index 3d0d053b5f..fb6bc96ae7 100644
--- a/db2/mp/mp_bh.c
+++ b/db2/mp/mp_bh.c
@@ -7,7 +7,7 @@
 #include "config.h"
 
 #ifndef lint
-static const char sccsid[] = "@(#)mp_bh.c	10.15 (Sleepycat) 8/29/97";
+static const char sccsid[] = "@(#)mp_bh.c	10.16 (Sleepycat) 9/23/97";
 #endif /* not lint */
 
 #ifndef NO_SYSTEM_INCLUDES
@@ -55,7 +55,7 @@ __memp_bhwrite(dbmp, mfp, bhp, restartp, wrotep)
 	 * If we find a descriptor on the file that's not open for writing, we
 	 * try and upgrade it to make it writeable.
 	 */
-	LOCKHANDLE(dbmp, &dbmp->mutex);
+	LOCKHANDLE(dbmp, dbmp->mutexp);
 	for (dbmfp = TAILQ_FIRST(&dbmp->dbmfq);
 	    dbmfp != NULL; dbmfp = TAILQ_NEXT(dbmfp, q))
 		if (dbmfp->mfp == mfp) {
@@ -64,7 +64,7 @@ __memp_bhwrite(dbmp, mfp, bhp, restartp, wrotep)
 				return (0);
 			break;
 		}
-	UNLOCKHANDLE(dbmp, &dbmp->mutex);
+	UNLOCKHANDLE(dbmp, dbmp->mutexp);
 	if (dbmfp != NULL)
 		goto found;
 
@@ -75,12 +75,12 @@ __memp_bhwrite(dbmp, mfp, bhp, restartp, wrotep)
 	 * nothing we can do.
 	 */
 	if (mfp->ftype != 0) {
-		LOCKHANDLE(dbmp, &dbmp->mutex);
+		LOCKHANDLE(dbmp, dbmp->mutexp);
 		for (mpreg = LIST_FIRST(&dbmp->dbregq);
 		    mpreg != NULL; mpreg = LIST_NEXT(mpreg, q))
 			if (mpreg->ftype == mfp->ftype)
 				break;
-		UNLOCKHANDLE(dbmp, &dbmp->mutex);
+		UNLOCKHANDLE(dbmp, dbmp->mutexp);
 		if (mpreg == NULL)
 			return (0);
 	}
@@ -135,19 +135,19 @@ __memp_pgread(dbmfp, bhp, can_create)
 	 * Seek to the page location.
 	 */
 	ret = 0;
-	LOCKHANDLE(dbmp, &dbmfp->mutex);
+	LOCKHANDLE(dbmp, dbmfp->mutexp);
 	if (dbmfp->fd == -1 || (ret =
 	    __db_lseek(dbmfp->fd, pagesize, bhp->pgno, 0, SEEK_SET)) != 0) {
 		if (!can_create) {
 			if (dbmfp->fd == -1)
 				ret = EINVAL;
-			UNLOCKHANDLE(dbmp, &dbmfp->mutex);
+			UNLOCKHANDLE(dbmp, dbmfp->mutexp);
 			__db_err(dbmp->dbenv,
 			    "%s: page %lu doesn't exist, create flag not set",
 			    dbmfp->path, (u_long)bhp->pgno);
 			goto err;
 		}
-		UNLOCKHANDLE(dbmp, &dbmfp->mutex);
+		UNLOCKHANDLE(dbmp, dbmfp->mutexp);
 
 		/* Clear any uninitialized data. */
 		memset(bhp->buf, 0, pagesize);
@@ -159,7 +159,7 @@ __memp_pgread(dbmfp, bhp, can_create)
 	 * any valid data is preserved.
 	 */
 	ret = __db_read(dbmfp->fd, bhp->buf, pagesize, &nr);
-	UNLOCKHANDLE(dbmp, &dbmfp->mutex);
+	UNLOCKHANDLE(dbmp, dbmfp->mutexp);
 	if (ret != 0)
 		goto err;
 
@@ -268,10 +268,10 @@ __memp_pgwrite(dbmfp, bhp, restartp, wrotep)
 	}
 
 	/* Temporary files may not yet have been created. */
-	LOCKHANDLE(dbmp, &dbmfp->mutex);
+	LOCKHANDLE(dbmp, dbmfp->mutexp);
 	if (dbmfp->fd == -1 && ((ret = __db_appname(dbenv, DB_APP_TMP,
 	    NULL, NULL, &dbmfp->fd, NULL)) != 0 || dbmfp->fd == -1)) {
-		UNLOCKHANDLE(dbmp, &dbmfp->mutex);
+		UNLOCKHANDLE(dbmp, dbmfp->mutexp);
 		__db_err(dbenv, "unable to create temporary backing file");
 		goto err;
 	}
@@ -282,7 +282,7 @@ __memp_pgwrite(dbmfp, bhp, restartp, wrotep)
 		fail = "seek";
 	else if ((ret = __db_write(dbmfp->fd, bhp->buf, pagesize, &nw)) != 0)
 		fail = "write";
-	UNLOCKHANDLE(dbmp, &dbmfp->mutex);
+	UNLOCKHANDLE(dbmp, dbmfp->mutexp);
 	if (ret != 0) {
 		/*
 		 * XXX
@@ -380,7 +380,7 @@ __memp_pg(dbmfp, bhp, is_pgin)
 	dbmp = dbmfp->dbmp;
 	mfp = dbmfp->mfp;
 
-	LOCKHANDLE(dbmp, &dbmp->mutex);
+	LOCKHANDLE(dbmp, dbmp->mutexp);
 
 	ftype = mfp->ftype;
 	for (mpreg = LIST_FIRST(&dbmp->dbregq);
@@ -394,7 +394,7 @@ __memp_pg(dbmfp, bhp, is_pgin)
 			dbt.data = ADDR(dbmp, mfp->pgcookie_off);
 			dbtp = &dbt;
 		}
-		UNLOCKHANDLE(dbmp, &dbmp->mutex);
+		UNLOCKHANDLE(dbmp, dbmp->mutexp);
 
 		if (is_pgin) {
 			if (mpreg->pgin != NULL && (ret =
@@ -408,11 +408,11 @@ __memp_pg(dbmfp, bhp, is_pgin)
 	}
 
 	if (mpreg == NULL)
-		UNLOCKHANDLE(dbmp, &dbmp->mutex);
+		UNLOCKHANDLE(dbmp, dbmp->mutexp);
 
 	return (0);
 
-err:	UNLOCKHANDLE(dbmp, &dbmp->mutex);
+err:	UNLOCKHANDLE(dbmp, dbmp->mutexp);
 	__db_err(dbmp->dbenv, "%s: %s failed for page %lu",
 	    dbmfp->path, is_pgin ? "pgin" : "pgout", (u_long)bhp->pgno);
 	return (ret);
diff --git a/db2/mp/mp_fget.c b/db2/mp/mp_fget.c
index 418802a3b9..a0364e92c3 100644
--- a/db2/mp/mp_fget.c
+++ b/db2/mp/mp_fget.c
@@ -7,7 +7,7 @@
 #include "config.h"
 
 #ifndef lint
-static const char sccsid[] = "@(#)mp_fget.c	10.22 (Sleepycat) 8/19/97";
+static const char sccsid[] = "@(#)mp_fget.c	10.25 (Sleepycat) 9/23/97";
 #endif /* not lint */
 
 #ifndef NO_SYSTEM_INCLUDES
@@ -35,7 +35,7 @@ int
 memp_fget(dbmfp, pgnoaddr, flags, addrp)
 	DB_MPOOLFILE *dbmfp;
 	db_pgno_t *pgnoaddr;
-	u_long flags;
+	int flags;
 	void *addrp;
 {
 	BH *bhp, *tbhp;
@@ -293,7 +293,7 @@ found:		/* Increment the reference count. */
 			__db_err(dbmp->dbenv,
 			    "%s: too many references to page %lu",
 			    dbmfp->path, bhp->pgno);
-			ret = EAGAIN;
+			ret = EINVAL;
 			goto err;
 		}
 		++bhp->ref;
@@ -337,9 +337,9 @@ found:		/* Increment the reference count. */
 		++mfp->stat.st_cache_hit;
 	}
 
-mapret:	LOCKHANDLE(dbmp, &dbmfp->mutex);
+mapret:	LOCKHANDLE(dbmp, dbmfp->mutexp);
 	++dbmfp->pinref;
-	UNLOCKHANDLE(dbmp, &dbmfp->mutex);
+	UNLOCKHANDLE(dbmp, dbmfp->mutexp);
 
 	if (0) {
 err:		/*
diff --git a/db2/mp/mp_fopen.c b/db2/mp/mp_fopen.c
index 1a770bfdf0..5ab807701c 100644
--- a/db2/mp/mp_fopen.c
+++ b/db2/mp/mp_fopen.c
@@ -7,7 +7,7 @@
 #include "config.h"
 
 #ifndef lint
-static const char sccsid[] = "@(#)mp_fopen.c	10.25 (Sleepycat) 8/27/97";
+static const char sccsid[] = "@(#)mp_fopen.c	10.27 (Sleepycat) 9/23/97";
 #endif /* not lint */
 
 #ifndef NO_SYSTEM_INCLUDES
@@ -28,8 +28,8 @@ static const char sccsid[] = "@(#)mp_fopen.c	10.25 (Sleepycat) 8/27/97";
 #include "common_ext.h"
 
 static int __memp_mf_close __P((DB_MPOOL *, DB_MPOOLFILE *));
-static int __memp_mf_open __P((DB_MPOOL *, DB_MPOOLFILE *,
-    int, int, size_t, int, DBT *, u_int8_t *, int, MPOOLFILE **));
+static int __memp_mf_open __P((DB_MPOOL *,
+    DB_MPOOLFILE *, int, size_t, int, DBT *, u_int8_t *, int, MPOOLFILE **));
 
 /*
  * memp_fopen --
@@ -97,7 +97,6 @@ __memp_fopen(dbmp, path,
 		    path == NULL ? TEMPORARY : path, strerror(ENOMEM));
 		return (ENOMEM);
 	}
-	LOCKINIT(dbmp, &dbmfp->mutex);
 	dbmfp->dbmp = dbmp;
 	dbmfp->fd = -1;
 	if (LF_ISSET(DB_RDONLY))
@@ -141,14 +140,21 @@ __memp_fopen(dbmp, path,
 		}
 	}
 
-	/* Find/allocate the shared file object. */
+	/*
+	 * Find/allocate the shared file objects.  This includes allocating
+	 * space for the per-process thread lock.
+	 */
 	if (needlock)
 		LOCKREGION(dbmp);
-	ret = __memp_mf_open(dbmp, dbmfp, ftype,
-	    F_ISSET(dbmfp, MP_READONLY), pagesize,
+	ret = __memp_mf_open(dbmp, dbmfp, ftype, pagesize,
 	    lsn_offset, pgcookie, fileid, F_ISSET(dbmfp, MP_PATH_TEMP), &mfp);
+	if (ret == 0 &&
+	    F_ISSET(dbmp, MP_LOCKHANDLE) && (ret =
+	    __memp_ralloc(dbmp, sizeof(db_mutex_t), NULL, &dbmfp->mutexp)) == 0)
+		LOCKINIT(dbmp, dbmfp->mutexp);
 	if (needlock)
 		UNLOCKREGION(dbmp);
+
 	if (ret != 0)
 		goto err;
 
@@ -156,11 +162,11 @@ __memp_fopen(dbmp, path,
 
 	/*
 	 * If a file:
-	 *
 	 *	+ is read-only
+	 *	+ isn't temporary
 	 *	+ doesn't require any pgin/pgout support
-	 *	+ is less than mp_mmapsize bytes in size.
-	 *	+ and the DB_NOMMAP flag wasn't set
+	 *	+ the DB_NOMMAP flag wasn't set
+	 *	+ and is less than mp_mmapsize bytes in size
 	 *
 	 * we can mmap it instead of reading/writing buffers.  Don't do error
 	 * checking based on the mmap call failure.  We want to do normal I/O
@@ -176,11 +182,20 @@ __memp_fopen(dbmp, path,
 	 * flatly impossible.  Hope that mmap fails if the file is too large.
 	 */
 #define	DB_MAXMMAPSIZE	(10 * 1024 * 1024)	/* 10 Mb. */
+	if (mfp->can_mmap) {
+		if (!F_ISSET(dbmfp, MP_READONLY))
+			mfp->can_mmap = 0;
+		if (path == NULL)
+			mfp->can_mmap = 0;
+		if (ftype != 0)
+			mfp->can_mmap = 0;
+		if (LF_ISSET(DB_NOMMAP))
+			mfp->can_mmap = 0;
+		if (size > (dbenv == NULL || dbenv->mp_mmapsize == 0 ?
+		    DB_MAXMMAPSIZE : (off_t)dbenv->mp_mmapsize))
+			mfp->can_mmap = 0;
+	}
 	dbmfp->addr = NULL;
-	mfp->can_mmap = F_ISSET(dbmfp, MP_READONLY) &&
-	    ftype == 0 && !LF_ISSET(DB_NOMMAP) && path != NULL &&
-	    size <= (dbenv == NULL || dbenv->mp_mmapsize == 0 ?
-	    DB_MAXMMAPSIZE : (off_t)dbenv->mp_mmapsize);
 	if (mfp->can_mmap) {
 		dbmfp->len = size;
 		if (__db_mmap(dbmfp->fd, dbmfp->len, 1, 1, &dbmfp->addr) != 0) {
@@ -189,14 +204,18 @@ __memp_fopen(dbmp, path,
 		}
 	}
 
-	LOCKHANDLE(dbmp, &dbmp->mutex);
+	LOCKHANDLE(dbmp, dbmp->mutexp);
 	TAILQ_INSERT_TAIL(&dbmp->dbmfq, dbmfp, q);
-	UNLOCKHANDLE(dbmp, &dbmp->mutex);
+	UNLOCKHANDLE(dbmp, dbmp->mutexp);
 
 	*retp = dbmfp;
 	return (0);
 
-err:	if (F_ISSET(dbmfp, MP_PATH_ALLOC))
+err:	/*
+	 * Note that we do not have to free the thread mutex, because we
+	 * never get to here after we have successfully allocated it.
+	 */
+	if (F_ISSET(dbmfp, MP_PATH_ALLOC))
 		FREES(dbmfp->path);
 	if (dbmfp->fd != -1)
 		(void)__db_close(dbmfp->fd);
@@ -211,10 +230,10 @@ err:	if (F_ISSET(dbmfp, MP_PATH_ALLOC))
  */
 static int
 __memp_mf_open(dbmp, dbmfp,
-    ftype, readonly, pagesize, lsn_offset, pgcookie, fileid, istemp, retp)
+    ftype, pagesize, lsn_offset, pgcookie, fileid, istemp, retp)
 	DB_MPOOL *dbmp;
 	DB_MPOOLFILE *dbmfp;
-	int ftype, readonly, lsn_offset, istemp;
+	int ftype, lsn_offset, istemp;
 	size_t pagesize;
 	DBT *pgcookie;
 	u_int8_t *fileid;
@@ -255,13 +274,8 @@ __memp_mf_open(dbmp, dbmfp,
 				mfp = NULL;
 				goto ret1;
 			}
-			/*
-			 * Found it: increment the reference count and update
-			 * the mmap-able status.
-			 */
+			/* Found it: increment the reference count. */
 			++mfp->ref;
-			if (!readonly)
-				mfp->can_mmap = 0;
 			goto ret1;
 		}
 
@@ -273,6 +287,7 @@ alloc:	if ((ret = __memp_ralloc(dbmp, sizeof(MPOOLFILE), NULL, &mfp)) != 0)
 	memset(mfp, 0, sizeof(MPOOLFILE));
 	mfp->ref = 1;
 	mfp->ftype = ftype;
+	mfp->can_mmap = 1;
 	mfp->lsn_off = lsn_offset;
 	mfp->stat.st_pagesize = pagesize;
 
@@ -343,9 +358,9 @@ memp_fclose(dbmfp)
 		    dbmfp->path, (u_long)dbmfp->pinref);
 
 	/* Remove the DB_MPOOLFILE structure from the list. */
-	LOCKHANDLE(dbmp, &dbmp->mutex);
+	LOCKHANDLE(dbmp, dbmp->mutexp);
 	TAILQ_REMOVE(&dbmp->dbmfq, dbmfp, q);
-	UNLOCKHANDLE(dbmp, &dbmp->mutex);
+	UNLOCKHANDLE(dbmp, dbmp->mutexp);
 
 	/* Close the underlying MPOOLFILE. */
 	(void)__memp_mf_close(dbmp, dbmfp);
@@ -362,11 +377,16 @@ memp_fclose(dbmfp)
 			t_ret = ret;
 	}
 
-	/* Potentially allocated path. */
+	/* Free memory. */
 	if (F_ISSET(dbmfp, MP_PATH_ALLOC))
 		FREES(dbmfp->path);
+	if (dbmfp->mutexp != NULL) {
+		LOCKREGION(dbmp);
+		__db_shalloc_free(dbmp->addr, dbmfp->mutexp);
+		UNLOCKREGION(dbmp);
+	}
 
-	/* Free the DB_MPOOLFILE structure. */
+	/* Discard the DB_MPOOLFILE structure. */
 	FREE(dbmfp, sizeof(DB_MPOOLFILE));
 
 	return (ret);
diff --git a/db2/mp/mp_fput.c b/db2/mp/mp_fput.c
index 5fac8ae76b..9ea7cd9d0d 100644
--- a/db2/mp/mp_fput.c
+++ b/db2/mp/mp_fput.c
@@ -7,7 +7,7 @@
 #include "config.h"
 
 #ifndef lint
-static const char sccsid[] = "@(#)mp_fput.c	10.10 (Sleepycat) 7/20/97";
+static const char sccsid[] = "@(#)mp_fput.c	10.12 (Sleepycat) 9/23/97";
 #endif /* not lint */
 
 #ifndef NO_SYSTEM_INCLUDES
@@ -31,7 +31,7 @@ int
 memp_fput(dbmfp, pgaddr, flags)
 	DB_MPOOLFILE *dbmfp;
 	void *pgaddr;
-	u_long flags;
+	int flags;
 {
 	BH *bhp;
 	DB_MPOOL *dbmp;
@@ -58,14 +58,14 @@ memp_fput(dbmfp, pgaddr, flags)
 	}
 
 	/* Decrement the pinned reference count. */
-	LOCKHANDLE(dbmp, &dbmfp->mutex);
+	LOCKHANDLE(dbmp, dbmfp->mutexp);
 	if (dbmfp->pinref == 0)
 		__db_err(dbmp->dbenv,
 		    "%s: put: more blocks returned than retrieved",
 		    dbmfp->path);
 	else
 		--dbmfp->pinref;
-	UNLOCKHANDLE(dbmp, &dbmfp->mutex);
+	UNLOCKHANDLE(dbmp, dbmfp->mutexp);
 
 	/*
 	 * If we're mapping the file, there's nothing to do.  Because we can
diff --git a/db2/mp/mp_fset.c b/db2/mp/mp_fset.c
index 588085a358..a3a3dcef9c 100644
--- a/db2/mp/mp_fset.c
+++ b/db2/mp/mp_fset.c
@@ -7,7 +7,7 @@
 #include "config.h"
 
 #ifndef lint
-static const char sccsid[] = "@(#)mp_fset.c	10.8 (Sleepycat) 8/19/97";
+static const char sccsid[] = "@(#)mp_fset.c	10.9 (Sleepycat) 9/20/97";
 #endif /* not lint */
 
 #ifndef NO_SYSTEM_INCLUDES
@@ -30,7 +30,7 @@ int
 memp_fset(dbmfp, pgaddr, flags)
 	DB_MPOOLFILE *dbmfp;
 	void *pgaddr;
-	u_long flags;
+	int flags;
 {
 	BH *bhp;
 	DB_MPOOL *dbmp;
diff --git a/db2/mp/mp_open.c b/db2/mp/mp_open.c
index 257ce1b9e9..f622b1ed26 100644
--- a/db2/mp/mp_open.c
+++ b/db2/mp/mp_open.c
@@ -7,7 +7,7 @@
 #include "config.h"
 
 #ifndef lint
-static const char sccsid[] = "@(#)mp_open.c	10.12 (Sleepycat) 7/6/97";
+static const char sccsid[] = "@(#)mp_open.c	10.13 (Sleepycat) 9/23/97";
 #endif /* not lint */
 
 #ifndef NO_SYSTEM_INCLUDES
@@ -56,7 +56,6 @@ memp_open(path, flags, mode, dbenv, retp)
 	/* Create and initialize the DB_MPOOL structure. */
 	if ((dbmp = (DB_MPOOL *)calloc(1, sizeof(DB_MPOOL))) == NULL)
 		return (ENOMEM);
-	LOCKINIT(dbmp, &dbmp->mutex);
 	LIST_INIT(&dbmp->dbregq);
 	TAILQ_INIT(&dbmp->dbmfq);
 
@@ -68,6 +67,17 @@ memp_open(path, flags, mode, dbenv, retp)
 		F_SET(dbmp, MP_ISPRIVATE);
 
 	/*
+	 * XXX
+	 * HP-UX won't permit mutexes to live in anything but shared memory.
+	 * So, we have to instantiate the shared mpool region file on that
+	 * architecture, regardless.  If this turns out to be a performance
+	 * problem, we could probably use anonymous memory instead.
+	 */
+#if defined(__hppa)
+	F_CLR(dbmp, MP_ISPRIVATE);
+#endif
+
+	/*
 	 * Map in the region.  We do locking regardless, as portions of it are
 	 * implemented in common code (if we put the region in a file, that is).
 	 */
@@ -79,12 +89,22 @@ memp_open(path, flags, mode, dbenv, retp)
 	/*
 	 * If there's concurrent access, then we have to lock the region.
 	 * If it's threaded, then we have to lock both the handles and the
-	 * region.
+	 * region, and we need to allocate a mutex for that purpose.
 	 */
 	if (!F_ISSET(dbmp, MP_ISPRIVATE))
 		F_SET(dbmp, MP_LOCKREGION);
-	if (LF_ISSET(DB_THREAD))
+	if (LF_ISSET(DB_THREAD)) {
 		F_SET(dbmp, MP_LOCKHANDLE | MP_LOCKREGION);
+		LOCKREGION(dbmp);
+		ret = __memp_ralloc(dbmp,
+		    sizeof(db_mutex_t), NULL, &dbmp->mutexp);
+		UNLOCKREGION(dbmp);
+		if (ret != 0) {
+			(void)memp_close(dbmp);
+			goto err;
+		}
+		LOCKINIT(dbmp, dbmp->mutexp);
+	}
 
 	*retp = dbmp;
 	return (0);
@@ -119,11 +139,18 @@ memp_close(dbmp)
 		if ((t_ret = memp_fclose(dbmfp)) != 0 && ret == 0)
 			ret = t_ret;
 
+	/* Discard thread mutex. */
+	if (F_ISSET(dbmp, MP_LOCKHANDLE)) {
+		LOCKREGION(dbmp);
+		__db_shalloc_free(dbmp->addr, dbmp->mutexp);
+		UNLOCKREGION(dbmp);
+	}
+
 	/* Close the region. */
 	if ((t_ret = __memp_rclose(dbmp)) && ret == 0)
 		ret = t_ret;
 
-	/* Free the structure. */
+	/* Discard the structure. */
 	FREE(dbmp, sizeof(DB_MPOOL));
 
 	return (ret);
@@ -168,9 +195,9 @@ memp_register(dbmp, ftype, pgin, pgout)
 	 * the most recent registry in the case of multiple entries, so
 	 * we don't have to check for multiple registries.
 	 */
-	LOCKHANDLE(dbmp, &dbmp->mutex);
+	LOCKHANDLE(dbmp, dbmp->mutexp);
 	LIST_INSERT_HEAD(&dbmp->dbregq, mpr, q);
-	UNLOCKHANDLE(dbmp, &dbmp->mutex);
+	UNLOCKHANDLE(dbmp, dbmp->mutexp);
 
 	return (0);
 }
diff --git a/db2/mutex/mutex.c b/db2/mutex/mutex.c
index b23f738ad7..5315b2d3fe 100644
--- a/db2/mutex/mutex.c
+++ b/db2/mutex/mutex.c
@@ -8,7 +8,7 @@
 #include "config.h"
 
 #ifndef lint
-static const char sccsid[] = "@(#)mutex.c	10.22 (Sleepycat) 8/21/97";
+static const char sccsid[] = "@(#)mutex.c	10.25 (Sleepycat) 9/23/97";
 #endif /* not lint */
 
 #ifndef NO_SYSTEM_INCLUDES
diff --git a/db2/os/db_os_dir.c b/db2/os/db_os_dir.c
index 6dabd62049..1206e3faa7 100644
--- a/db2/os/db_os_dir.c
+++ b/db2/os/db_os_dir.c
@@ -8,7 +8,7 @@
 #include "config.h"
 
 #ifndef lint
-static const char sccsid[] = "@(#)db_os_dir.c	10.8 (Sleepycat) 8/27/97";
+static const char sccsid[] = "@(#)db_os_dir.c	10.10 (Sleepycat) 9/17/97";
 #endif /* not lint */
 
 #ifndef NO_SYSTEM_INCLUDES
@@ -60,9 +60,11 @@ __db_dir(dbenv, dir, namesp, cntp)
 	struct _finddata_t fdata;
 	long dirhandle;
 	int finished;
+	char filespec[MAX_PATH];
 
-	if ((dirhandle = _findfirst(dir, &fdata)) == -1) {
-		__db_err(dbenv, "%s: %s", dir, strerror(errno));
+	(void)snprintf(filespec, sizeof(filespec), "%s/*", dir);
+	if ((dirhandle = _findfirst(filespec, &fdata)) == -1) {
+		__db_err(dbenv, "%s: %s", filespec, strerror(errno));
 		return (errno);
 	}
 
diff --git a/db2/progs/db_checkpoint/db_checkpoint.c b/db2/progs/db_checkpoint/db_checkpoint.c
index 4f9b79a7ba..b2a692bba9 100644
--- a/db2/progs/db_checkpoint/db_checkpoint.c
+++ b/db2/progs/db_checkpoint/db_checkpoint.c
@@ -11,7 +11,7 @@
 static const char copyright[] =
 "@(#) Copyright (c) 1997\n\
 	Sleepycat Software Inc.  All rights reserved.\n";
-static const char sccsid[] = "@(#)db_checkpoint.c	10.11 (Sleepycat) 8/27/97";
+static const char sccsid[] = "@(#)db_checkpoint.c	10.12 (Sleepycat) 9/4/97";
 #endif
 
 #ifndef NO_SYSTEM_INCLUDES
@@ -22,6 +22,7 @@ static const char sccsid[] = "@(#)db_checkpoint.c	10.11 (Sleepycat) 8/27/97";
 #include <signal.h>
 #include <stdio.h>
 #include <stdlib.h>
+#include <string.h>
 #include <time.h>
 #include <unistd.h>
 #endif
@@ -59,7 +60,7 @@ main(argc, argv)
 	DB_ENV *dbenv;
 	time_t now;
 	long kbytes, minutes, seconds;
-	int ch, rval, verbose;
+	int ch, eval, verbose;
 	char *home, *logfile;
 
 	home = logfile = NULL;
@@ -110,7 +111,7 @@ main(argc, argv)
 	 * to wake up when a checkpoint is necessary.  If we have a "kbytes"
 	 * field set, then we'll check every 30 seconds.
 	 */
-	rval = 0;
+	eval = 0;
 	seconds = kbytes != 0 ? 30 : minutes * 60;
 	while (!interrupted) {
 		(void)__db_sleep(seconds, 0);
@@ -119,23 +120,25 @@ main(argc, argv)
 			(void)time(&now);
 			printf("checkpoint: %s", ctime(&now));
 		}
-		rval = txn_checkpoint(dbenv->tx_info, kbytes, minutes);
-		if (rval < 0)
-			break;
+		errno = txn_checkpoint(dbenv->tx_info, kbytes, minutes);
 
-		while (rval > 0) {
+		while (errno == DB_INCOMPLETE) {
 			if (verbose)
 				__db_err(dbenv,
 				    "checkpoint did not finish, retrying");
 			(void)__db_sleep(2, 0);
-			rval = txn_checkpoint(dbenv->tx_info, 0, 0);
+			errno = txn_checkpoint(dbenv->tx_info, 0, 0);
 		}
-		if (rval < 0)
+
+		if (errno != 0) {
+			eval = 1;
+			__db_err(dbenv, "checkpoint: %s", strerror(errno));
 			break;
+		}
 	}
 
 	if (logfile != NULL && logpid(logfile, 0))
-		rval = 1;
+		eval = 1;
 
 	if (interrupted) {
 		(void)signal(interrupted, SIG_DFL);
@@ -143,7 +146,7 @@ main(argc, argv)
 		/* NOTREACHED */
 	}
 
-	return (db_appexit(dbenv) || rval ? 1 : 0);
+	return (db_appexit(dbenv) || eval ? 1 : 0);
 }
 
 /*
diff --git a/db2/progs/db_deadlock/db_deadlock.c b/db2/progs/db_deadlock/db_deadlock.c
index 09004f58b3..ec2b53dee7 100644
--- a/db2/progs/db_deadlock/db_deadlock.c
+++ b/db2/progs/db_deadlock/db_deadlock.c
@@ -11,7 +11,7 @@
 static const char copyright[] =
 "@(#) Copyright (c) 1997\n\
 	Sleepycat Software Inc.  All rights reserved.\n";
-static const char sccsid[] = "@(#)db_deadlock.c	10.14 (Sleepycat) 8/27/97";
+static const char sccsid[] = "@(#)db_deadlock.c	10.15 (Sleepycat) 9/4/97";
 #endif
 
 #ifndef NO_SYSTEM_INCLUDES
diff --git a/db2/progs/db_dump185/db_dump185.c b/db2/progs/db_dump185/db_dump185.c
index 6e2d95bee0..5ec7673f1b 100644
--- a/db2/progs/db_dump185/db_dump185.c
+++ b/db2/progs/db_dump185/db_dump185.c
@@ -11,7 +11,7 @@
 static const char copyright[] =
 "@(#) Copyright (c) 1997\n\
 	Sleepycat Software Inc.  All rights reserved.\n";
-static const char sccsid[] = "@(#)db_dump185.c	10.7 (Sleepycat) 8/27/97";
+static const char sccsid[] = "@(#)db_dump185.c	10.8 (Sleepycat) 9/21/97";
 #endif
 
 #ifndef NO_SYSTEM_INCLUDES
@@ -192,7 +192,7 @@ main(argc, argv)
 
 	if ((dbp = dbopen(argv[0], O_RDONLY, 0, DB_BTREE, NULL)) == NULL) {
 		if ((dbp = dbopen(argv[0], O_RDONLY, 0, DB_HASH, NULL)) == NULL)
-			return (1);
+			err(1, "%s", argv[0]);
 		db_185_hash(dbp, pflag);
 	} else
 		db_185_btree(dbp, pflag);
diff --git a/db2/progs/db_load/db_load.c b/db2/progs/db_load/db_load.c
index 6f69216777..a1ebfa8a11 100644
--- a/db2/progs/db_load/db_load.c
+++ b/db2/progs/db_load/db_load.c
@@ -11,7 +11,7 @@
 static const char copyright[] =
 "@(#) Copyright (c) 1997\n\
 	Sleepycat Software Inc.  All rights reserved.\n";
-static const char sccsid[] = "@(#)db_load.c	10.12 (Sleepycat) 8/28/97";
+static const char sccsid[] = "@(#)db_load.c	10.13 (Sleepycat) 9/15/97";
 #endif
 
 #ifndef NO_SYSTEM_INCLUDES
@@ -59,7 +59,7 @@ main(argc, argv)
 	char **clist, **clp, *home;
 
 	/* Allocate enough room for configuration arguments. */
-	if ((clp = clist = calloc(argc + 1, sizeof(char *))) == NULL)
+	if ((clp = clist = (char **)calloc(argc + 1, sizeof(char *))) == NULL)
 		err(1, NULL);
 
 	home = NULL;
diff --git a/db2/progs/db_recover/db_recover.c b/db2/progs/db_recover/db_recover.c
index d17c4b0c76..55b9b49a79 100644
--- a/db2/progs/db_recover/db_recover.c
+++ b/db2/progs/db_recover/db_recover.c
@@ -11,7 +11,7 @@
 static const char copyright[] =
 "@(#) Copyright (c) 1997\n\
 	Sleepycat Software Inc.  All rights reserved.\n";
-static const char sccsid[] = "@(#)db_recover.c	10.14 (Sleepycat) 8/27/97";
+static const char sccsid[] = "@(#)db_recover.c	10.15 (Sleepycat) 9/21/97";
 #endif
 
 #ifndef NO_SYSTEM_INCLUDES
@@ -24,6 +24,7 @@ static const char sccsid[] = "@(#)db_recover.c	10.14 (Sleepycat) 8/27/97";
 #endif
 
 #include "db_int.h"
+#include "shqueue.h"
 #include "txn.h"
 #include "common_ext.h"
 #include "clib_ext.h"
diff --git a/db2/txn/txn.c b/db2/txn/txn.c
index cb700dc037..9a0d626c3e 100644
--- a/db2/txn/txn.c
+++ b/db2/txn/txn.c
@@ -43,16 +43,10 @@
 #include "config.h"
 
 #ifndef lint
-static const char sccsid[] = "@(#)txn.c	10.24 (Sleepycat) 9/3/97";
+static const char sccsid[] = "@(#)txn.c	10.30 (Sleepycat) 9/23/97";
 #endif /* not lint */
 
 
-/*
- * This file contains the top level routines of the transaction library.
- * It assumes that a lock manager and log manager that conform to the db_log(3)
- * and db_lock(3) interfaces exist.
- */
-
 #ifndef NO_SYSTEM_INCLUDES
 #include <sys/types.h>
 #include <sys/mman.h>
@@ -87,10 +81,12 @@ static int __txn_undo __P((DB_TXN *));
 static int __txn_validate_region __P((DB_TXNMGR *));
 
 /*
+ * This file contains the top level routines of the transaction library.
+ * It assumes that a lock manager and log manager that conform to the db_log(3)
+ * and db_lock(3) interfaces exist.
+ *
  * Create and initialize a transaction region in shared memory.
- * 0 means, success.
- * +1 means that the db_create failed, so we did not create the region.
- * -1 means that we got some sort of system error.
+ * Return 0 on success, errno on failure.
  */
 static int
 __txn_create(dbenv, path, mode)
@@ -99,9 +95,8 @@ __txn_create(dbenv, path, mode)
 	u_int mode;
 {
 	DB_TXNREGION *txn_region;
-	TXN_DETAIL *txnp;
 	time_t now;
-	int fd, i, maxtxns, ret;
+	int fd, maxtxns, ret;
 
 	maxtxns = dbenv->tx_max != 0 ? dbenv->tx_max : 1000;
 	(void)time(&now);
@@ -120,17 +115,12 @@ __txn_create(dbenv, path, mode)
 	/* XXX If we ever do more types of locking and logging, this changes. */
 	txn_region->logtype = 0;
 	txn_region->locktype = 0;
-	txn_region->free_txn = 0;
 	txn_region->time_ckp = now;
 	ZERO_LSN(txn_region->last_ckp);
 	ZERO_LSN(txn_region->pending_ckp);
-
-	for (txnp = &txn_region->table[0], i = 0; i < maxtxns; i++, txnp++) {
-		ZERO_LSN(txnp->begin_lsn);
-		txnp->status = TXN_UNALLOC;
-		txnp->txnid = i + 1;
-	}
-	txn_region->table[maxtxns - 1].txnid = TXN_INVALID;
+	SH_TAILQ_INIT(&txn_region->active_txn);
+	__db_shalloc_init((void *)&txn_region[1],
+	    TXN_REGION_SIZE(maxtxns) - sizeof(DB_TXNREGION));
 
 	/* Unlock the region. */
 	(void)__db_mutex_unlock(&txn_region->hdr.lock, fd);
@@ -140,7 +130,6 @@ __txn_create(dbenv, path, mode)
 		(void)txn_unlink(path, 1 /* force */, dbenv);
 		return (ret);
 	}
-
 	return (0);
 }
 
@@ -199,7 +188,7 @@ retry1:	if ((ret = __db_ropen(dbenv, DB_APP_NONE, path, DEFAULT_TXN_FILE,
 
 	/* Now, create the transaction manager structure and set its fields. */
 	if ((tmgrp = (DB_TXNMGR *)malloc(sizeof(DB_TXNMGR))) == NULL) {
-		__db_err(dbenv, "txn_open: %s", strerror(errno));
+		__db_err(dbenv, "txn_open: %s", strerror(ENOMEM));
 		ret = ENOMEM;
 		goto out;
 	}
@@ -211,9 +200,18 @@ retry1:	if ((ret = __db_ropen(dbenv, DB_APP_NONE, path, DEFAULT_TXN_FILE,
 	tmgrp->reg_size = txn_regionp->hdr.size;
 	tmgrp->fd = fd;
 	tmgrp->flags = LF_ISSET(DB_TXN_NOSYNC | DB_THREAD);
+	tmgrp->mem = &txn_regionp[1];
+	tmgrp->mutexp = NULL;
 	TAILQ_INIT(&tmgrp->txn_chain);
-	if (LF_ISSET(DB_THREAD))
-		__db_mutex_init(&tmgrp->mutex, -1);
+	if (LF_ISSET(DB_THREAD)) {
+		LOCK_TXNREGION(tmgrp);
+		if ((ret = __db_shalloc(tmgrp->mem, sizeof(db_mutex_t), 
+		    MUTEX_ALIGNMENT, &tmgrp->mutexp)) == 0)
+			__db_mutex_init(tmgrp->mutexp, -1);
+		UNLOCK_TXNREGION(tmgrp);
+		if (ret != 0)
+			goto out;
+	}
 	*mgrpp = tmgrp;
 	return (0);
 
@@ -221,8 +219,14 @@ out:	if (txn_regionp != NULL)
 		(void)__db_rclose(dbenv, fd, txn_regionp);
 	if (flags & DB_CREATE)
 		(void)txn_unlink(path, 1, dbenv);
-	if (tmgrp != NULL)
+	if (tmgrp != NULL) {
+		if (tmgrp->mutexp != NULL) {
+			LOCK_TXNREGION(tmgrp);
+			__db_shalloc_free(tmgrp->mem, tmgrp->mutexp);
+			UNLOCK_TXNREGION(tmgrp);
+		}
 		free(tmgrp);
+	}
 	return (ret);
 }
 
@@ -239,30 +243,20 @@ txn_begin(tmgrp, parent, txnpp)
 {
 	TXN_DETAIL *txnp;
 	DB_TXN *retp;
-	int id, index, ret;
+	int id, ret;
 
 	LOCK_TXNREGION(tmgrp);
 
-	if ((ret = __txn_validate_region(tmgrp)) != 0) {
-		UNLOCK_TXNREGION(tmgrp);
-		return (ret);
-	}
-
-	/* Remove element from free list. */
-	if (tmgrp->region->free_txn == TXN_INVALID &&
-	    (ret = __txn_grow_region(tmgrp)) != 0) {
-		UNLOCK_TXNREGION(tmgrp);
-		return (ret);
-	}
-
-	index = tmgrp->region->free_txn;
-	txnp = &tmgrp->region->table[index];
-	tmgrp->region->free_txn = txnp->txnid;
+	if ((ret = __txn_validate_region(tmgrp)) != 0)
+		goto err;
 
-	if (txnp->status != TXN_UNALLOC) {
-		UNLOCK_TXNREGION(tmgrp);
-		return (EINVAL);
-	}
+	/* Allocate a new transaction detail structure. */
+	if ((ret = __db_shalloc(tmgrp->mem, sizeof(TXN_DETAIL), 0, &txnp)) != 0
+	    && ret == ENOMEM && (ret = __txn_grow_region(tmgrp)) == 0)
+	    	ret = __db_shalloc(tmgrp->mem, sizeof(TXN_DETAIL), 0, &txnp);
+		
+	if (ret != 0)
+		goto err;
 
 	/* Make sure that last_txnid is not going to wrap around. */
 	if (tmgrp->region->last_txnid == TXN_INVALID)
@@ -270,18 +264,20 @@ txn_begin(tmgrp, parent, txnpp)
 
 	if ((retp = (DB_TXN *)malloc(sizeof(DB_TXN))) == NULL) {
 		__db_err(tmgrp->dbenv, "txn_begin : %s", strerror(ENOMEM));
-		UNLOCK_TXNREGION(tmgrp);
-		return (ENOMEM);
+		ret = ENOMEM;
+		goto err1;
 	}
 
 	id = ++tmgrp->region->last_txnid;
 	tmgrp->region->nbegins++;
 
 	txnp->txnid = id;
-	txnp->last_lock = 0;
-	txnp->status = TXN_RUNNING;
 	ZERO_LSN(txnp->last_lsn);
 	ZERO_LSN(txnp->begin_lsn);
+	txnp->last_lock = 0;
+	txnp->status = TXN_RUNNING;
+	SH_TAILQ_INSERT_HEAD(&tmgrp->region->active_txn,
+	    txnp, links, __txn_detail);
 
 	UNLOCK_TXNREGION(tmgrp);
 
@@ -297,8 +293,9 @@ txn_begin(tmgrp, parent, txnpp)
 
 		/* Deallocate transaction. */
 		LOCK_TXNREGION(tmgrp);
-		txnp->txnid = tmgrp->region->free_txn;
-		tmgrp->region->free_txn = txnp - &tmgrp->region->table[0];
+		SH_TAILQ_REMOVE(&tmgrp->region->active_txn,
+		    txnp, links, __txn_detail);
+		__db_shalloc_free(tmgrp->mem, txnp);
 		UNLOCK_TXNREGION(tmgrp);
 		free (retp);
 		return (ret);
@@ -310,6 +307,12 @@ txn_begin(tmgrp, parent, txnpp)
 
 	*txnpp  = retp;
 	return (0);
+
+err1:
+	__db_shalloc_free(tmgrp->mem, txnp);
+err:
+	UNLOCK_TXNREGION(tmgrp);
+	return (ret);
 }
 
 /* The db_txn(3) man page describes txn_commit. */
@@ -362,16 +365,15 @@ txn_prepare(txnp)
 	int ret;
 	TXN_DETAIL *tp;
 
-	ret = 0;
 	if ((ret = __txn_check_running(txnp)) != 0)
 		return (ret);
 
-	if (txnp->mgrp->dbenv->lg_info) {
-		ret = log_flush(txnp->mgrp->dbenv->lg_info, &txnp->last_lsn);
-		if (ret)
+	if (txnp->mgrp->dbenv->lg_info != NULL) {
+		if ((ret = log_flush(txnp->mgrp->dbenv->lg_info,
+		    &txnp->last_lsn)) != 0)
 			__db_err(txnp->mgrp->dbenv,
 			    "txn_prepare: log_flush failed %s\n",
-			    strerror(errno));
+			    strerror(ret));
 		return (ret);
 	}
 
@@ -420,12 +422,19 @@ txn_close(tmgrp)
 	    ret == 0)
 		ret = t_ret;
 
+	if (tmgrp->mutexp != NULL) {
+		LOCK_TXNREGION(tmgrp);
+		__db_shalloc_free(tmgrp->mem, tmgrp->mutexp);
+		UNLOCK_TXNREGION(tmgrp);
+	}
+
 	if ((t_ret = __db_rclose(tmgrp->dbenv, tmgrp->fd, tmgrp->region)) != 0
 	    && ret == 0)
 		ret = t_ret;
 
 	if (ret == 0)
 		free (tmgrp);
+
 	return (ret);
 }
 
@@ -499,9 +508,8 @@ __txn_end(txnp, is_commit)
 	/* End the transaction. */
 	LOCK_TXNREGION(mgr);
 	tp = (TXN_DETAIL *)((u_int8_t *)mgr->region + txnp->off);
-	tp->status = TXN_UNALLOC;
-	tp->txnid = mgr->region->free_txn;
-	mgr->region->free_txn = tp - &mgr->region->table[0];
+	SH_TAILQ_REMOVE(&mgr->region->active_txn, tp, links, __txn_detail);
+	__db_shalloc_free(mgr->mem, tp);
 	if (is_commit)
 		mgr->region->ncommits++;
 	else
@@ -515,8 +523,9 @@ __txn_end(txnp, is_commit)
 
 
 /*
- * Undo the transaction with id txnid.  Returns 0 on success and sets
- * errno and returns -1 on failure.
+ * __txn_undo --
+ *	Undo the transaction with id txnid.  Returns 0 on success and
+ *	errno on failure.
  */
 static int
 __txn_undo(txnp)
@@ -576,12 +585,12 @@ __txn_undo(txnp)
 int
 txn_checkpoint(mgr, kbytes, minutes)
 	const DB_TXNMGR *mgr;
-	long kbytes, minutes;
+	int kbytes, minutes;
 {
 	TXN_DETAIL *txnp;
 	DB_LSN ckp_lsn, last_ckp;
 	DB_LOG *dblp;
-	u_int32_t bytes_written, i;
+	u_int32_t bytes_written;
 	time_t last_ckp_time, now;
 	int ret;
 
@@ -638,16 +647,16 @@ do_ckp:
 	if (!IS_ZERO_LSN(mgr->region->pending_ckp))
 		ckp_lsn = mgr->region->pending_ckp;
 	else
-		for (txnp = &mgr->region->table[0], i = 0;
-		    i < mgr->region->maxtxns; i++, txnp++) {
+		for (txnp =
+		    SH_TAILQ_FIRST(&mgr->region->active_txn, __txn_detail);
+		    txnp != NULL;
+		    txnp = SH_TAILQ_NEXT(txnp, links, __txn_detail)) {
 
 			/*
-			 * Look through the transaction table for the LSN of
-			 * the transaction that is in-use (e.g., not
-			 * TXN_UNALLOC) and whose begin lsn is the lowest.
+			 * Look through the active transactions for the
+			 * lowest begin lsn.
 			 */
-			if (txnp->status != TXN_UNALLOC &&
-			    !IS_ZERO_LSN(txnp->begin_lsn) &&
+			if (!IS_ZERO_LSN(txnp->begin_lsn) &&
 			    log_compare(&txnp->begin_lsn, &ckp_lsn) < 0)
 				ckp_lsn = txnp->begin_lsn;
 		}
@@ -707,6 +716,7 @@ __txn_validate_region(tp)
 		return (ret);
 
 	tp->reg_size = tp->region->hdr.size;
+	tp->mem = &tp->region[1];
 
 	return (0);
 }
@@ -715,9 +725,9 @@ static int
 __txn_grow_region(tp)
 	DB_TXNMGR *tp;
 {
-	TXN_DETAIL *tx;
 	size_t incr;
-	u_int32_t i, oldmax;
+	u_int32_t oldmax;
+	u_int8_t *curaddr;
 	int ret;
 
 	oldmax = tp->region->maxtxns;
@@ -729,19 +739,17 @@ __txn_grow_region(tp)
 	if ((ret = __db_rremap(tp->dbenv, tp->region,
 	    tp->reg_size, tp->reg_size + incr, tp->fd, &tp->region)) != 0)
 		return (ret);
+
+	/* Throw the new space on the free list. */
+	curaddr = (u_int8_t *)tp->region + tp->reg_size;
+	tp->mem = &tp->region[1];
 	tp->reg_size += incr;
 
-	/*
-	 * Initialize all the new transactions and up the transaction count.
-	 */
-	for (i = 0, tx = &tp->region->table[oldmax]; i < oldmax; i++, tx++) {
-		ZERO_LSN(tx->begin_lsn);
-		tx->status = TXN_UNALLOC;
-		tx->txnid = oldmax + i + 1;
-	}
-	tp->region->free_txn = oldmax;
+	*((size_t *)curaddr) = incr - sizeof(size_t);
+	curaddr += sizeof(size_t);
+	__db_shalloc_free(tp->mem, curaddr);
+
 	tp->region->maxtxns = 2 * oldmax;
-	tp->region->table[tp->region->maxtxns - 1].txnid = TXN_INVALID;
 
 	return (0);
 }
@@ -753,8 +761,9 @@ txn_stat(mgr, statp, db_malloc)
 	void *(*db_malloc) __P((size_t));
 {
 	DB_TXN_STAT *stats;
+	TXN_DETAIL *txnp;
 	size_t nbytes;
-	u_int32_t i, nactive, ndx;
+	u_int32_t nactive, ndx;
 
 	LOCK_TXNREGION(mgr);
 	nactive = mgr->region->nbegins -
@@ -789,17 +798,17 @@ txn_stat(mgr, statp, db_malloc)
 		stats->st_nactive = nactive + 200;
 	stats->st_txnarray = (DB_TXN_ACTIVE *)&stats[1];
 
-	for (ndx = 0, i = 0; i < mgr->region->maxtxns; i++)
-		if (mgr->region->table[i].status != TXN_UNALLOC) {
-			stats->st_txnarray[ndx].txnid =
-			    mgr->region->table[i].txnid;
-			stats->st_txnarray[ndx].lsn =
-			    mgr->region->table[i].begin_lsn;
-			ndx++;
+	ndx = 0;
+	for (txnp = SH_TAILQ_FIRST(&mgr->region->active_txn, __txn_detail);
+	    txnp != NULL;
+	    txnp = SH_TAILQ_NEXT(txnp, links, __txn_detail)) {
+		stats->st_txnarray[ndx].txnid = txnp->txnid;
+		stats->st_txnarray[ndx].lsn = txnp->begin_lsn;
+		ndx++;
 
-			if (ndx >= stats->st_nactive)
-				break;
-		}
+		if (ndx >= stats->st_nactive)
+			break;
+	}
 
 	UNLOCK_TXNREGION(mgr);
 	*statp = stats;
diff --git a/db2/txn/txn_auto.c b/db2/txn/txn_auto.c
index c7f277ed0f..baef7333c7 100644
--- a/db2/txn/txn_auto.c
+++ b/db2/txn/txn_auto.c
@@ -92,7 +92,7 @@ __txn_regop_print(notused1, dbtp, lsnp, notused3, notused4)
 	notused3 = 0;
 	notused4 = NULL;
 
-	if((ret = __txn_regop_read(dbtp->data, &argp)) != 0)
+	if ((ret = __txn_regop_read(dbtp->data, &argp)) != 0)
 		return (ret);
 	printf("[%lu][%lu]txn_regop: rec: %lu txnid %lx prevlsn [%lu][%lu]\n",
 	    (u_long)lsnp->file,
@@ -221,7 +221,7 @@ __txn_ckp_print(notused1, dbtp, lsnp, notused3, notused4)
 	notused3 = 0;
 	notused4 = NULL;
 
-	if((ret = __txn_ckp_read(dbtp->data, &argp)) != 0)
+	if ((ret = __txn_ckp_read(dbtp->data, &argp)) != 0)
 		return (ret);
 	printf("[%lu][%lu]txn_ckp: rec: %lu txnid %lx prevlsn [%lu][%lu]\n",
 	    (u_long)lsnp->file,